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; 

また、配列参照の配列参照内のデータにアクセスするには、単純に逆参照演算子を使用します。

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

さらに、配列参照の配列参照を作成する方法 (配列の配列への参照を取る) や、参照としてすぐに作成することができます。

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

補足として、識別名として$aandを使用しないでください$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']);

...他の配列への参照である 3 つのスカラー値のみが含まれます。次のように記述できます。

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;
于 2012-08-17T17:18:53.810 に答える
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 に答える
1

「最後」の使用は、内側または外側のあいまいであることがわかったので、明示的にしました。

for (@$a) {
    INNER:
    for (@$_) {
        do {$_ = $d; last INNER} if $_ eq $s;
    }
}
于 2012-08-17T16:19:59.160 に答える
0
for my $x (@{$a}) {
    for (@{$x}) {
        if ($_ eq $s) {
            $_ = $d;
            last;
        }
    }
}
于 2012-08-17T15:17:56.927 に答える