6

$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;
4

6 回答 6

18
foreach my $row (@$array_ref) {
    foreach my $cell (@$row) {
        if ($cell eq $s) {
            $cell = $d;
            last;
        }
    }
}

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

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.

此外,您可以按照您的方式创建您的 arrayrefs (获取对数组数组的引用),或者立即作为参考:

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

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

于 2012-08-17T15:19:15.833 回答
4

要在 Perl 中取消引用,您有多种选择。对于初学者,我建议您阅读perlref。这是相关的代码部分,更改最少,因此您可以看到需要有所不同的地方(但是,我同意其他人的建议,以使您的代码更加 Perlish)。

for my $i ( 0 .. $#$a ) {
    for my $j ( 0 .. $#{ $a->[$i] } ) {
        if ($a->[$i][$j] eq $s) {
            $a->[$i][$j] = $d;
            last;
        }
    }
}
于 2012-08-17T15:23:04.220 回答
3

在我看来,取消引用的最简单方法是始终记住数组和哈希只能包含量值(请参阅perldoc perldata)。这意味着你的数组

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
    }
}

Also, since the values in a for loop are aliased, any changes to them affects the original array. So if the "processing" in the loop above contains an assignment such as

$value = $foo;

That means that the values in @all are also changed, exactly as if you had written:

$all[0][1] = $foo;
于 2012-08-17T17:18:53.810 回答
1

我发现“last”的使用是模棱两可的,内部或外部,所以我明确表示。

for (@$a) {
    INNER:
    for (@$_) {
        do {$_ = $d; last INNER} if $_ eq $s;
    }
}
于 2012-08-17T16:19:59.160 回答
1

每当我处理数组或哈希数组或哈希数组或数组哈希数组时,我都会开始考虑面向对象编程。Perl OOP 并不是那么复杂,它隐藏了很多逻辑复杂性。

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

但是一旦你开始意识到你可以在 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};
}
于 2012-08-17T17:18:34.437 回答
0
for my $x (@{$a}) {
    for (@{$x}) {
        if ($_ eq $s) {
            $_ = $d;
            last;
        }
    }
}
于 2012-08-17T15:17:56.927 回答