Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

looping over multidimensional arrays

by Anonymous Monk
on Sep 20, 2018 at 14:23 UTC ( #1222715=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Couldn't find the answer to this anywhere, but it should be a fairly simple question for an expert (which I am not).

If I have an array @x, that I have, say, initialized up to $x[5][11], is there some way of looping over the rows (and then the columns within each row) without setting up the classic for loops with counters such as $i and $j? I read somewhere that if you are using counters in perl, you are not doing it right, so I am wondering about other syntax (foreach?) that might do that.

Replies are listed 'Best First'.
Re: looping over multidimensional arrays
by LanX (Archbishop) on Sep 20, 2018 at 14:35 UTC
    for my $a1 (@x) { for my $a2 (@$a1) { for my $a3 (@$a2) { ... # hope you get the pattern by now } } }

    For covering arbitrary depth of nesting you could apply a recursive function (a so called "walker")

    If the elements are other than array_refs you might want to add cases after testing ref $aX.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: looping over multidimensional arrays
by Marshall (Abbot) on Sep 20, 2018 at 15:42 UTC
    I hope this code is of help...
    A multi-dimensional array is built by making arrays of references to array. You don't get to the actual data until the last dimension.
    Here I explicitly build a 2D structure, what is called an AoA (Array of Array).
    #!/usr/bin/perl use strict; use warnings; use Data::Dump qw(pp); my @row1 = qw(a b c); my @row2 = qw(d e f); my @AoA = (\@row1, \@row2); pp \@AoA; # [["a", "b", "c"], ["d", "e", "f"]] foreach my $my_row_ref (@AoA) { print "@$my_row_ref \n"; } #a b c #d e f print "$AoA[1][1]\n"; #prints "e" #print column1... foreach my $my_row_ref (@AoA) { print "$my_row_ref->[1] \n"; } #b #e
Re: looping over multidimensional arrays
by AnomalousMonk (Chancellor) on Sep 20, 2018 at 16:57 UTC

    Another approach using array slices.

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @AoA = ( [ '00' .. '09' ], [ '10' .. '19' ], [ '20' .. '29' ], [ '30' .. '39' ], ); dd \@AoA; ;; print join '-', @{ $AoA[1] }[ 3 .. 7 ]; print qq{@{ $AoA[2] }[ 2 .. 5 ]}; " [ ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09"], [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], [20, 21, 22, 23, 24, 25, 26, 27, 28, 29], [30, 31, 32, 33, 34, 35, 36, 37, 38, 39], ] 13-14-15-16-17 22 23 24 25
    See also Perl Data Structures Cookbook.


    Give a man a fish:  <%-{-{-{-<

Re: looping over multidimensional arrays
by BillKSmith (Parson) on Sep 20, 2018 at 20:12 UTC
    You can usually replace the innermost loop with a map.
    ?type 1222715.pl use strict; use warnings; use Data::Dumper; my @array = ( [qw(0a 0b 0c 0d 0e 0f 0g 0h 0i 0j 0k)], [qw(1a 1b 1c 1d 1e 1f 1g 1h 1i 1j 1k)], [qw(2a 2b 2c 2d 2e 2f 2g 2h 2i 2j 2k)], [qw(3a 3b 3c 3d 3e 3f 3g 3h 3i 3j 3k)], [qw(4a 4b 4c 4d 4e 4f 4g 4h 4i 4j 4k)], ); my @array_new; foreach my $vec (@array) { push @array_new, [map {myfunc($_)} @$vec]; } print Dumper(\@array_new); sub myfunc { return "$_[0]_new"; } ?perl 1222715.pl $VAR1 = [ [ '0a_new', '0b_new', '0c_new', '0d_new', '0e_new', '0f_new', '0g_new', '0h_new', '0i_new', '0j_new', '0k_new' ], [ '1a_new', '1b_new', '1c_new', '1d_new', '1e_new', '1f_new', '1g_new', '1h_new', '1i_new', '1j_new', '1k_new' ], ... ]; ?
    Bill
Re: looping over multidimensional arrays
by haukex (Chancellor) on Sep 23, 2018 at 08:02 UTC
    I read somewhere that if you are using counters in perl, you are not doing it right

    That's probably a bit of an exaggeration to make a point: People coming from other languages will be used to C-style for loops, but often Perl's foreach will do away with a need to use indicies in the first place.

    But sometimes you need an index, and there, instead of for (my $i; $i<@a; $i++), the more Perlish ways are for my $i (0..$#a) or, on newer versions of Perl, you can use each.

    Note: This is a re-post of a node that was lost.

Re: looping over multidimensional arrays
by Laurent_R (Canon) on Sep 20, 2018 at 21:24 UTC
    See also the answers to this post for additional solutions and information: Joining array into new string

    This is an example with map, shown here at the command line:

    $ perl -we 'use strict; > use Data::Dumper; > my @AoA = ( ["a" .. "d"], ["e" .. "h"]); > print Dumper \@AoA; > print "\n", map { "@$_ "} @AoA;' $VAR1 = [ [ 'a', 'b', 'c', 'd' ], [ 'e', 'f', 'g', 'h' ] ]; a b c d e f g h

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1222715]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2019-06-20 03:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Is there a future for codeless software?



    Results (89 votes). Check out past polls.

    Notices?