Arrays 如何循环一个数组作为引用?

Arrays 如何循环一个数组作为引用?,arrays,perl,reference,Arrays,Perl,Reference,如果$a是一个数组,那么下面的代码可以工作,但我需要$a作为数组的引用 问题 如何遍历$a #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my @AoA = ( ['aaa','hdr','500'], ['bbb','jid','424'], ['ccc','rde','402'], ); my $a = \@AoA; my $s = "bb

如果
$a
是一个数组,那么下面的代码可以工作,但我需要
$a
作为数组的引用

问题

如何遍历
$a

#!/usr/bin/perl

use warnings;
use strict;
use Data::Dumper;

my @AoA = ( ['aaa','hdr','500'],
            ['bbb','jid','424'],
            ['ccc','rde','402'],
            );

my $a = \@AoA;

my $s = "bbb";
my $d = "ddd";

for my $i ( 0 .. $#a ) {
    for my $j ( 0 .. $#{ $a[$i] } ) {
        if ($a[$i][$j] eq $s) {
            $a[$i][$j] = $d;
            last;
        }
    }
}

print Dumper $a;
此外,要计算数组引用中元素的#数(从上面的代码中可以看出,特定代码不需要这些元素),最简单的方法是:

my $count = scalar(@$array_ref);
my $row_count = scalar(@{ $array_ref->[$i] });
my $last_index = $#$array_ref; 
此外,要访问arrayrefs的arrayref中的数据,只需对其使用解引用操作符:

$array_ref->[$i]->[$j]; # The second arrow is optional but I hate omitting it.
此外,您还可以像以前那样创建arrayref of arrayrefs(引用array of arrays),或者立即创建arrayref of arrayrefs作为引用:

my $array_ref = [
         [1,2,3]
         ,[4,5,6]
        ];

作为旁注,请不要使用
$a
$b
作为标识符名称-它们有特殊用途(例如在排序块中使用)

要在Perl中取消引用,您有多种选择。首先,我建议你阅读。这里是相关的代码部分,改动最少,因此您可以看到哪些地方需要有所不同(不过,我同意其他人的建议,让您的代码更完美)

我发现“last”的用法是模棱两可的,无论是内在的还是外在的,所以我把它明确了

for (@$a) {
    INNER:
    for (@$_) {
        do {$_ = $d; last INNER} if $_ eq $s;
    }
}

每当我处理数组、散列、散列或数组的散列数组时,我就开始考虑面向对象编程。PerlOOP并没有那个么复杂,它隐藏了很多逻辑复杂性

现在,在这个非常简单的例子中,如果不使用面向对象的方法编写它,将会容易得多,而且您已经有了几个好的答案(您主要忘记了取消引用)

但是,一旦您开始意识到Perl中的结构比简单的散列、数组和标量更复杂,您的数据结构就会变得更复杂,并且在没有OOP的情况下更难解析

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

my $a_of_a = array_of_arrays->new;

$a_of_a->push(["aaa", "hdr", "500"]);
$a_of_a->push(["bbb", "jid", "424"]);
$a_of_a->push(["ccc", "rde", "402"]);

foreach my $member ($a_of_a->list) {
    my @array = @{$member};
    foreach my $element (@array) {
        printf "%-5.5s  ", $element;
    }
    print "\n";
}


package array_of_arrays;

sub new {
    my $class = shift;
    my $self = [];

    bless $self, $class;
    return $self;
}

sub push {
    my $self = shift;
    my $item = shift;

    push @{$self}, $item;
    return $self;
}

sub pop {
    my $self = shift;

    if (scalar @{$self}) {
        return pop @{$self};
    }
    else {
        return;
    }
}

sub list {
    my $self = shift;
    return @{$self};
}

在我看来,解除引用的最简单方法是始终记住数组和散列只能包含标量值(请参阅)。这意味着你的数组

my @AoA = ( ['aaa','hdr','500'],
            ['bbb','jid','424'],
            ['ccc','rde','402']);
…仅包含三个标量值,它们是对其他数组的引用。你可以这样写:

my $first = [ qw(aaa hdr 500) ];      # using qw() which will quote the args
my $sec   = [ qw(bbb jid 424) ];
my $third = [ qw(ccc rde 402) ];
my @all   = ($first, $sec, $third);   # this array is now identical to @AoA
考虑到这一点,很容易想象(如DVK在其回答中所建议的)一个循环,如:

for my $aref (@all) {
    # $aref will contain $first, $sec, and $third 
}
知道
$aref
是一个数组引用,解引用很简单:

for my $aref (@all) {
    for my $value (@$aref) {
        # do your processing here
    }
}
此外,由于for循环中的值具有别名,因此对它们的任何更改都会影响原始数组。因此,如果上面循环中的“处理”包含如下赋值

$value = $foo;
这意味着
@all
中的值也会发生更改,就像您编写的:

$all[0][1] = $foo;

$#$a
也起作用,并给出最后一个数组索引,这是本例中所需要的。丑陋?也许吧,但是标量(@$a)也不是很直观。@dan-是的,为了完整性,我加入了$#$操作。它并没有那么难看,但可读性较差,而且肯定没那么有用。在Perl中,我很少需要在索引增量上执行C风格的循环。我同意应该避免C风格的循环,但是(0..$#array){}的
通常很有用。+1用于使用数组引用而不是索引。IMO索引只能在特定的元信息用于其他目的时使用。问得好!其实我也在想同样的事情。
for my $aref (@all) {
    for my $value (@$aref) {
        # do your processing here
    }
}
$value = $foo;
$all[0][1] = $foo;