如何循环数组数组作为参考?

时间:2012-08-17 15:12:59

标签: 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 = "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;

6 个答案:

答案 0 :(得分:14)

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内的数据,只需在其上使用dereference运算符:

$array_ref->[$i]->[$j]; # The second arrow is optional but I hate omitting it.

此外,你可以像你所做的那样创建arrayrefs的arrayref(引用数组数组),或者立即创建它作为参考:

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

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

答案 1 :(得分:3)

要在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;
        }
    }
}

答案 2 :(得分: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
    }
}

此外,由于for循环中的值是别名,因此对它们的任何更改都会影响原始数组。因此,如果上面循环中的“处理”包含诸如

之类的赋值
$value = $foo;

这意味着@all中的值也会发生变化,就像你写的那样:

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

答案 3 :(得分:1)

我发现使用“last”是模糊的,内在的或外在的,所以我明确表示。

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

答案 4 :(得分: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};
}

答案 5 :(得分:0)

for my $x (@{$a}) {
    for (@{$x}) {
        if ($_ eq $s) {
            $_ = $d;
            last;
        }
    }
}