【问题标题】:How can I dereference an array of arrays in Perl?如何取消引用 Perl 中的数组数组?
【发布时间】:2010-10-13 14:59:44
【问题描述】:

如何在传递给函数时取消对数组数组的引用?

我是这样做的:

my @a = {\@array1, \@array2, \@array3};

func(\@a);


func{
    @b = @_;

    @c = @{@b};
}

其实我希望数组@c应该包含@array1@array2@array3的地址。

【问题讨论】:

  • 我不认为@a={\@array1, \@array2, \@array3} 做你认为它做的事情。
  • 这么少的代码行有这么多的误解。
  • Perl 有引用,而不是指针(如 C)。你不能得到变量的地址,你也不需要。 (对于那些不得不指出这不是 100% 准确的熟练 Perl 黑客:不要。OP 已经够糊涂了。)
  • 如果您不首先尝试使用use strict; use warnings; 运行您的代码,那么您就是在浪费每个人的时间(包括您自己的,我认为这对您来说是最宝贵的)。

标签: perl perl-data-structures


【解决方案1】:
my @a = {\@array1, \@array2, \@array3};

上面是一个包含单个成员的数组 -> 一个 hash 包含:

{ ''.\@array1 => \@array2, ''.\@array3 => undef }

因为作为散列中的键,Perl 将@array1 的引用强制转换为字符串。 Perl 允许将标量哈希引用分配给数组,因为“理解”您想要一个数组,其中第一个元素是您分配给它的标量。

您创建一个数组数组,如下所示:

my @a = (\@array1, \@array2, \@array3);

然后在你的函数中解压它们,像这样:

sub func {
    my $ref = shift;
    foreach my $arr ( @$ref ) {
        my @list_of_values = @$arr;
    }
}

或者它的一些变体,比如说地图是最简单的表达方式:

my @list_of_entries = map { @$_ } @$ref;

在您的示例中,@c 作为地址列表与正确构造的@a 完全相同。

【讨论】:

    【解决方案2】:

    你可能想阅读perldoc perlreftutperldoc perlrefperldoc perldsc你可以说:

    sub func {
        my $arrayref = shift;
    
        for my $aref (@$arrayref) {
            print join(", ", @$aref), "\n";
        }
    }
    
    my @array1 = (1, 2, 3);
    my @array2 = (4, 5, 6);
    my @array3 = (7, 8, 9);
    
    my @a = \(@array1, @array2, @array3);
    
    func \@a;
    

    或更简洁:

    sub func {
        my $arrayref = shift;
    
        for my $aref (@$arrayref) {
            print join(", ", @$aref), "\n";
        }
    }
    
    func [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ];
    

    【讨论】:

      【解决方案3】:

      阅读perlreftut 文档。

      编辑:其他人指出了我起初错过的一个好点。在@a 的初始化中,您可能指的是@a = (...)(创建包含引用的数组)或$arrayref = [...](创建对数组的引用),而不是{...}(创建对哈希的引用)。本文的其余部分假设您拥有@a = (...) 版本。

      由于您将一个参数(对@a 的引用)传递给func,因此@_ 是一个包含该引用的列表。您可以获取该引用,然后通过执行以下操作取消引用它:

      sub func {
        my $arrayref = shift;
        my @c = @{$arrayref};
      }
      

      或者在一行中,它看起来像:

      sub func {
        my @c = @{shift()};
      }
      

      (如果您没有在 func(\@a) 中使用反斜杠,@_ 将等于 @a,三个引用的数组。)

      【讨论】:

        【解决方案4】:

        以下函数旨在获取一个数组或数组引用,并返回一个唯一值的排序数组。未定义的值被移除,HASH 和 GLOB 保持原样。

        #!/usr/bin/perl
        use strict; use warnings;
        
        my @one = qw / dog rat / ;
        my @two = qw / dog mice / ;
        my @tre = ( "And then they said it!", "No!??  ", );
        open my $H, '<', $0 or die "unable to open $0 to read";
        my $dog; # to show behavior with undefined value
        my %hash; $hash{pig}{mouse}=55; # to show that it leaves HASH alone
        my $rgx = '(?is)dog'; $rgx = qr/$rgx/; # included for kicks
        
        my @whoo =  (
            'hey!',
            $dog, # undefined
            $rgx,
            1, 2, 99, 999, 55.5, 3.1415926535,
            %hash,
            $H,
            [ 1, 2, 
                      [ 99, 55, \@tre, ],
            3, ],
                \@one, \@two,
                [ 'fee', 'fie,' ,
                    [ 'dog', 'dog', 'mice', 'gopher', 'piranha', ],
                    [ 'dog', 'dog', 'mice', 'gopher', 'piranha', ],
                ],
                [ 1, [ 1, 2222, ['no!', 'no...', 55, ], ], ],
                [ [ [ 'Rat!', [ 'Non,', 'Tu es un rat!' , ], ], ], ], 
                'Hey!!',
                0.0_1_0_1,
                -33,
        );
        
        
        print join ( "\n", 
            recursively_dereference_sort_unique_array( [ 55, 9.000005555, ], @whoo, \@one, \@whoo, [ $H ], ),
            "\n", );
        close $H;
        exit;
        
        sub recursively_dereference_sort_unique_array
        {
            # recursively dereference array of arrays; return unique values sorted. Leave HASH and GLOB (filehandles) as they are.
            # 2020v10v04vSunv12h20m15s
            my $sb_name = (caller(0))[3];
            @_ = grep defined, @_; #https://stackoverflow.com/questions/11122977/how-do-i-remove-all-undefs-from-array
            my @redy = grep { !/^ARRAY\x28\w+\x29$/ } @_; # redy==the subset that is "ready"
            my @noty = grep {  /^ARRAY\x28\w+\x29$/ } @_; # noty==the subset that is "not yet"
            my $countiter = 0;
            while (1)
            {
                $countiter++; 
                die "$sb_name: are you in an infinite loop?" if ($countiter > 99);
                my @next;
                foreach my $refarray ( @noty )
                {
                    my @tmparray = @$refarray;
                    push    @next, @tmparray;
                }
                @next = grep defined, @next;
                my @okay= grep { !/^ARRAY\x28\w+\x29$/ } @next;
                @noty   = grep {  /^ARRAY\x28\w+\x29$/ } @next;
                push @redy, @okay;
                my %hash = map { $_ => 1 } @redy; # trick to get unique values
                @redy    = sort keys %hash;
                return @redy unless (scalar @noty);
            }
        }
        
        

        【讨论】:

          【解决方案5】:

          应该是

          func {
              $b = shift;
          }
          

          如果您要传递参考。希望对大家有所帮助。

          【讨论】:

            猜你喜欢
            • 2021-03-23
            • 1970-01-01
            • 1970-01-01
            • 2012-06-22
            • 1970-01-01
            • 2021-07-04
            • 2018-02-25
            • 1970-01-01
            • 2016-04-25
            相关资源
            最近更新 更多