Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Arrays in arrays, how to access them

by viored (Novice)
on Oct 29, 2013 at 20:29 UTC ( #1060217=perlquestion: print w/replies, xml ) Need Help??
viored has asked for the wisdom of the Perl Monks concerning the following question:

So I have a project I'm working on, and I'm having some difficulty. What I'm trying to do is to have several arrays of differing length which are stored in a master array. So, say I have @a1, @a2, and @a3 and I want to store them in @M. or @M=(@a1,@a2,@a3) but then I'd also like to be able to make changes to the arrays in the master array and apply functions to them just like I would any array. &subfunc(@M[0]) for instance. For this, I'd like to do some subroutine on the first array in the master array. but I'm a bit lost. What should I do?

Replies are listed 'Best First'.
Re: Arrays in arrays, how to access them
by Laurent_R (Abbot) on Oct 29, 2013 at 22:07 UTC

    You can't really have nested arrays the way you seem to think about them in Perl. An array is just a collection of ordered scalars. So, if you try to do something like this:

    my @master_array = (1, 3, (5, 9, 4), 2, (8, 7), 6);

    you will not get an array of arrays, but just a flat array containing all the values listed above, just as if you had declared it this way:

    my @master_array = (1, 3, 5, 9, 4, 2, 8, 7, 6);

    But you can nonetheless build nested data structure by the use of references: some of the scalars of your array might be references to other arrays.

    For example you could do this:

    my @subarray1 = (5, 9, 4); my @subarray2 = (8, 7); my @master_array = (1, 3, \@subarray1, 2, \@subarray2, 6);

    Here, $master_array[2] contains \@subarray1, which is a scalar containing a reference to the @subarray1 array. You could now access the 9 value with the following syntax:

    my $value = $master_array[2][1];

    To change 9 to 10, just use it the other way around:

    $master_array[2][1] = 10;

    You can also use the [] array reference constructor to obtain the same result:

    my $subarray1_ref = [5, 9, 4]; my @master_array = (1, 3, $subarray1_ref, 2, [8, 7], 6);

    This gives you a first idea about what you can do, but you definitely need to read the documentation about Perl references and data structure to go further. The place to start is the Perl Data Structure Cookbook:

Re: Arrays in arrays, how to access them
by state-o-dis-array (Hermit) on Oct 29, 2013 at 21:58 UTC

    Hi viored, and welocome to the monestary!

    The following should give you a good start: perldsc perlref

    Not knowing more about what you are doing, for your sub call, I might do something like:

    subcall( \@{$M[0]} );
    Which passes a reference to the first array in @M.

      subcall( \@{$M[0]} );

      Which passes a reference to the first array in @M.

      So it does, but if the array  @M is initialized per something like
          my @M = (\@a1, \@a2, \@a3);
      then the elements of  @M are all array references to begin with, so why not just
      and avoid taking a reference to a de-referenced array reference?

      (And see also perllol "Manipulating Arrays of Arrays in Perl".) (Update: And also perlreftut.)

        When I use
        subcall( $M[0] );
        I get ARRAY(0xa07b5d8), not a the output of the function I'm interested in. Same thing for
        subcall( \@{M[0]} )
        What am I missing?
        Ah, but if I use
        subcall ( @{\@{$M[0]}} )
        It works. Thank you so much, both of of you.
Re: Arrays in arrays, how to access them
by viored (Novice) on Oct 29, 2013 at 23:17 UTC
    Thanks for the data structures link. I'll be reading through it. But maybe I'm going about my problem in the wrong way. So, what I'm trying to do, in simplest terms, is have many arrays, with each array containing multiple strings, and then I want to be able to do operations on those strings in an iterative fashion. I thought an array of arrays would do it, but I'm not very familiar with perl. Would you suggest that I store things a different way?

      So you want to have a bunch of strings

      So you want to stuff those strings under one thing, one bucket, one box, one variable

      So you want to have an array-of-strings

      So you have more than one array-of-strings

      So keeping more than one array-of-strings in an array, seems natural

      Unlesss, you want to name each and every one of those arrays of bunches of things, then keep them in a hash

      #!/usr/bin/perl -- use strict; use warnings; my @feet = qw/ left right /; my @shoes = qw/ loafer sneaker boot /; my @lowers = ( \@feet, \@shoes ); ## $lower{feet} is prounounced lower-of-feet ## $lower{shoes} is prounounced lower-of-shoes my %lower = ( feet => [ @feet ], shoes => [ @shoes ] ); print "$lower{feet}[0] $lower{shoes}[0]\n"; print "$lower{feet}[1] $lower{shoes}[1]\n"; print "----\n"; for my $lower ( @lowers ){ for my $low ( @$lower ){ print " $low "; } print "\n"; } print "----\n"; ## while( my( $key, $value ) = each %lower ){ while( my( $lower, $of_array ) = each %lower ){ print "$lower $_\n" for @$of_array; }
      foreach, each, Tutorials: Data Type: Array, references quick reference

      More elaborate and coprehensive tutorial in, Learn Perl in about 2 hours 30 minutes, perlintro, chromatics free book Modern Perl a loose description of how experienced and effective Perl 5 programmers work....You can learn this too.

      Anonymous Monk has proposed a hash of arrays data structure, which enables you to name the sub_arrays. This is fine if you need to names these arrays. If you don't particularly need to name them, then the array of arrays structure that I outline above is just as fine for what you want to do. You could have something like this:

      my @array = ([$str_1_1, $str_1-2], [$str_2_1, $str_2_2]);

      It is then easy to process the strings of any subarray.

      Update 08:35 UTC: added the following examples under the Perl debugger:

      DB<1> @array = (["str_1_1", "str_1-2"], ["str_2_1", "str_2_2"]) DB<2> DB<2> x @array 0 ARRAY(0x253a70) 0 'str_1_1' 1 'str_1-2' 1 ARRAY(0x58f8a8) 0 'str_2_1' 1 'str_2_2' DB<3> x $array[1] 0 ARRAY(0x58f8a8) 0 'str_2_1' 1 'str_2_2' DB<4> p "$array[1][$_] \n" for 0..1 str_2_1 str_2_2

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1060217]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (9)
As of 2017-02-27 16:47 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (389 votes). Check out past polls.