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;