http://www.perlmonks.org?node_id=1146597

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

I have a question about asking elements of an array. Suppose I have an array
my @shapes = ( [qw/circle square triangle polygon/], [qw/red green blue yellow fuschia/], [qw/a b c d e f g h i j k/] , [qw/Movie TV Radio/] , );
How do I access elements 2 onwards for each row? The size of each row is different and not known before hand. Thanks
  • Comment on How do I access only certain elements of a multidimensional array?
  • Download Code

Replies are listed 'Best First'.
Re: How do I access only certain elements of a multidimensional array?
by AnomalousMonk (Archbishop) on Nov 01, 2015 at 02:31 UTC

    c:\@Work\Perl\monks>perl -wMstrict -le "my @shapes = ( [qw/circle square triangle polygon/], [qw/red green blue yellow fuschia/], [qw/a b c d e f g h i j k/] , [qw/Movie TV Radio/] , ); ;; for my $arrayref (@shapes) { printf qq{'$_' } for @{$arrayref}[ 2 .. $#$arrayref ]; print ''; } " 'triangle' 'polygon' 'blue' 'yellow' 'fuschia' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'Radio'
    See perldsc. (Update: And also Slices in perldata.)

    Update: Or if you don't want to use a slice, maybe

    c:\@Work\Perl\monks>perl -wMstrict -le "my @shapes = ( [qw/circle square triangle polygon/], [qw/red green blue yellow fuschia/], [qw/a b c d e f g h i j k/] , [qw/Movie TV Radio/] , ); ;; for my $arrayref (@shapes) { printf qq{'$arrayref->[$_]' } for 2 .. $#$arrayref; print ''; } " 'triangle' 'polygon' 'blue' 'yellow' 'fuschia' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'Radio'


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

      I just knew how to access one specific column. But now I know how to do this. Thank you :)
      What if I had to choose what rows to pick? I tried the following code and it did not work for me
      foreach my $i ( 2 .. $#shapes ) { print $out_ph1 '$_' for @{$i}[ 2 .. $#$i]; print $out_ph1 ''\n"; }
      I am trying to access row 2 onwards
        I could think of several ways, but this seemed the easiest to understand and write. :)
        foreach my $aref (@shapes[2 .. $#shapes]) { print join(" ", @$aref[2 .. $#$aref]), "\n"; }
        Output:
        c d e f g h i j k Radio
        Hope this is helpful.

        Further to Cristoforo's reply above:     Ppeoc: Indeed, the  @shapes array (from the OP) is an array, and an array slice works on any array:

        c:\@Work\Perl\monks>perl -wMstrict -le "my @shapes = ( [qw/circle square triangle polygon/], [qw/red green blue yellow fuschia/], [qw/a b c d e f g h i j k/] , [qw/Movie TV Radio/] , ); ;; for my $arrayref (@shapes[ 2, 0, 2 ]) { printf qq{'$_' } for @{$arrayref}[ 2 .. $#$arrayref ]; print ''; } " 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'triangle' 'polygon' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k'
        Furthermore, the slice list does not have to be a range, but is a list of any indices, including repeats, in any order.

        If you want to create an entirely new array as 2teez is doing with map below, you can do something like this:

        c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @shapes = ( [qw/circle square triangle polygon/], [qw/red green blue yellow fuschia/], [qw/a b c d e f g h i j k/] , [qw/Movie TV Radio/] , ); ;; my @new_ra = map { [ @{$_}[ 2 .. $#$_ ] ] } @shapes[ 2, 0, 2 ] ; dd \@new_ra; " [["c" .. "k"], ["triangle", "polygon"], ["c" .. "k"]]

        Update: Array and hash slices are a very convenient notational shortcut, but it's possible to avoid them if you wish. Try to understand the slice examples given and try to work out on your own a variation that does not use slices. If you need help with this, please post again in this thread.


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

Re: How do I access only certain elements of a multidimensional array?
by igoryonya (Pilgrim) on Nov 01, 2015 at 05:53 UTC
    I incorrectly understood the question at first (thought, you wanted to access the 2nd column), now, I see, you want to access each row from the 2nd to the last element:
    my @new_shapes = (); map { push(@new_shapes, [@$_[2..$#$_]]) } @shapes;
    if you want to access, say from 1 to 4, just change:
    [2..$#$_] to: [1..4]

      Hi igoryonya,

      map { push(@new_shapes, [@$_[2..$#$_]]) } @shapes;

      I probably not use map like you are using.
      Maybe something like so:

      my @new_shapes = map { [ @{$_}[ 2 .. $#$_ ] ] } @shapes; print join( " " => @{$_} ), $/ for @new_shapes;
      Output:
      triangle polygon blue yellow fuschia c d e f g h i j k Radio

      If you tell me, I'll forget.
      If you show me, I'll remember.
      if you involve me, I'll understand.
      --- Author unknown to me
        :), yea, it's better, condenses my 2 lines into 1.