How to iterate over an array of arrays as a reference?

This code works if $a is an array of arrays, but I need $a to reference an array of arrays.

Question

How to 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; 
+4
source share
6 answers
 foreach my $row (@$array_ref) { foreach my $cell (@$row) { if ($cell eq $s) { $cell = $d; last; } } } 

Also, to compute # elements in an array reference (which, as you can see from the above code, you don't need for your specific code), the easiest way:

 my $count = scalar(@$array_ref); my $row_count = scalar(@{ $array_ref->[$i] }); my $last_index = $#$array_ref; 

Also, to access the data inside arrayref 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 arrefrefs array as you did (take a link to an array of arrays) or immediately as a link:

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

As a note, please never use $a and $b as identifier names - they have a special purpose (for example, they are used in sorting blocks)

+13
source

You have many options for dereferencing in Perl. First, I suggest you read perlref . Here is the relevant piece of code with minimal modifications, so you can see what should be different (however, I agree with the suggestions of others 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; } } } 
+3
source

I found using the "latter" ambiguous, internal or external, so I made it explicit.

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

Whenever I deal with arrays of arrays or hashes or hashes or arrays of hashes of arrays, I start thinking in terms of object-oriented programming. Perl OOP is not that complicated, and it hides a lot of logical complexity.

Now, in this very simple example, it would be much easier to write it without object orientation, and you already have some good answers (you basically forgot to dereference your links).

But as soon as you begin to realize that you may have more complex structures in Perl than simple hashes, arrays, and scalars, your data structures become 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}; } 
+1
source

The easiest way to dereference, in my opinion, is to always remember that arrays and hashes can only contain scalar values ​​(see perldoc perldata ). That means your array

 my @AoA = ( ['aaa','hdr','500'], ['bbb','jid','424'], ['ccc','rde','402']); 

... contains only three scalar values, which are links to other arrays. You can 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’s easy to imagine (e.g. DVK in your answer) a loop, for example:

 for my $aref (@all) { # $aref will contain $first, $sec, and $third } 

And knowing that $aref is an array reference, dereferencing is simple:

 for my $aref (@all) { for my $value (@$aref) { # do your processing here } } 

In addition, since the values ​​in the for loop are smoothed, any changes to them affect the original array. Therefore, if the β€œprocessing” in the loop above contains an assignment such as

 $value = $foo; 

This means that the values ​​in @all also changed, just as if you wrote:

 $all[0][1] = $foo; 
+1
source
 for my $x (@{$a}) { for (@{$x}) { if ($_ eq $s) { $_ = $d; last; } } } 
0
source

All Articles