Reputation: 26046
The below code works if $a
is an Array of Arrays, but I need $a
to be an reference to the Array of Arrays.
Question
How do I iterate through $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;
Upvotes: 7
Views: 20429
Reputation: 67910
The easiest way to dereference, in my opinion, is to always remember that arrays and hashes can only ever contain scalar values (see perldoc perldata). Which means that your array
my @AoA = ( ['aaa','hdr','500'],
['bbb','jid','424'],
['ccc','rde','402']);
...contains only three scalar values, which are references to other arrays. You could write it like this:
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
With this in mind, it is simple to imagine (like DVK suggested in his answer) a loop such as:
for my $aref (@all) {
# $aref will contain $first, $sec, and $third
}
And knowing that $aref
is an array reference, the dereferencing is simple:
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;
Upvotes: 4
Reputation: 107090
Whenever I deal with arrays of arrays or hashes or hashes or arrays of hashes of arrays, I start to think in terms of Object Oriented programming. Perl OOP isn't all that complex, and it hides a lot of the logical complexity.
Now, in this very simple example, it would be a lot easier just to write it without object orientation, and you already have several good answers (you mainly forgot to dereference your references).
But once you start realizing that you can have more complex structures in Perl than simple hashes, arrays, and scalars, your data structures start getting more complex and more difficult to parse without 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};
}
Upvotes: 1
Reputation: 9026
I found the use of "last" to be ambiguous, inner or outer, so I made it explicit.
for (@$a) {
INNER:
for (@$_) {
do {$_ = $d; last INNER} if $_ eq $s;
}
}
Upvotes: 1
Reputation: 129529
foreach my $row (@$array_ref) {
foreach my $cell (@$row) {
if ($cell eq $s) {
$cell = $d;
last;
}
}
}
Also, to compute the # of elements in array reference (which as you can see from above code you don't need for your specific code), the easiest approach is:
my $count = scalar(@$array_ref);
my $row_count = scalar(@{ $array_ref->[$i] });
my $last_index = $#$array_ref;
Also, to access the data inside an arrayref of arrayrefs, you simply use the dereference operator on it:
$array_ref->[$i]->[$j]; # The second arrow is optional but I hate omitting it.
In addition, you can create your arrayref of arrayrefs the way you did (take a reference to array of arrays), or right away as a reference:
my $array_ref = [
[1,2,3]
,[4,5,6]
];
As a side note, please never use $a
and $b
as identifyer names - they have special purpose (used in sort blocks for example)
Upvotes: 18
Reputation: 6566
To dereference in Perl, you have a variety of options. For starters, I suggest you read perlref. Here is the relevant code portion with a minimum of changes, so you can see what needs to be different (however, I agree with others' suggestions to make your code more Perlish).
for my $i ( 0 .. $#$a ) {
for my $j ( 0 .. $#{ $a->[$i] } ) {
if ($a->[$i][$j] eq $s) {
$a->[$i][$j] = $d;
last;
}
}
}
Upvotes: 4
Reputation: 1128
for my $x (@{$a}) {
for (@{$x}) {
if ($_ eq $s) {
$_ = $d;
last;
}
}
}
Upvotes: 0