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

Hello, I have to work with random tables so number of rows and columns can vary everytime. I want to save rows and columns in multidimentional array. However as number of rows and columns can vary everytime i am unable to understand how to proceed. Can anybody please tell help me for this Thank you.
  • Comment on Creating multidimentional arrays dynamically

Replies are listed 'Best First'.
Re: Creating multidimentional arrays dynamically
by Marshall (Canon) on Aug 13, 2010 at 05:56 UTC
    The Perl way for something like that is called an AoA (Array of Array). The first dimension consists entirely of pointers and the data is in the attached arrays - this just like it is done in the 'C' language.

    update: added another example. I also will point out that data types within an AoA can be mixed - this can't be done in C! But in Perl it is perfectly ok and used quite often. Maybe a row is like: ("Smith", "Bob", 1932, $ref2otherdata)!

    #!/usr/bin/perl -w use strict; my @a = ([1,2,3], [9,8,7,6,5]); print "$a[0][1] the 2 in first row\n"; print "$a[1][3] the 6 in the second row\n"; print "showing another way to make a 2-d thing\n"; # often the syntax that allows access to individual elements just # isn't used as often processing a whole row at once is what is needed my $rows = 3; my $cols = 4; my @x; while ($rows--) { my @rand; push(@rand, int rand(100)) foreach (1..$cols); push (@x, [@rand]); } foreach my $array_ref (@x) { print "@$array_ref\n"; } __END__ prints: 2 the 2 in first row 6 the 6 in the second row 62 44 73 13 11 14 23 73 47 22 40 9
    These arrays like @a can of course be built dynamically and the number of columns in each row do not have to be equal - this is called a "ragged array" although here they are. Above shows one way to generate a AoA and note that I didn't use any kind of [x][y] coordinates to either generate the 2-D array or to print it. Perl is designed to do thinks like process the entire row easily.

    There are other types of Perl data structures that can represent data like what you have given us a hint about and some of these are less obviously 'C' like. It would be helpful if you could provide some additional application data. An AoH is also used often and gets away from stuff like index3 means "name" and avoids this #define name 3 sort of statements or their equivalents that are so prevalent in other languages. Anyway if you have heterogeneous stuff stored in the 2D array, there are some cool ways to deal with that.

      Except unlike C or some other languages, you don't need to specify size of array when creating etc..just add more elements as you see fit.
      the hardest line to type correctly is: stty erase ^H
        Actually that sort of stuff happens all the time in C. Hey, let's make row 12 longer (e.g. add more "columns" to that specific row) or add more rows overall. You may be thinking of what I call "traditional C 2D arrays" vs dynamically created arrays.

        Now having said that, you have to write a lot more code to make all that work in 'C' than you have to write in Perl. That is for sure! Perl arrays were designed to be easy to use and they are! A Perl AoA has essentially the same approach as a dynamic C 2D array, i.e. the first part is a array of pointers to arrays that describe the rows.

Re: Creating multidimentional arrays dynamically
by sflitman (Hermit) on Aug 13, 2010 at 05:54 UTC
    Here's a 2D example, using neat Perl syntax:
    #!/usr/bin/perl use strict; use warnings; my @x; for my $i (0..3) { for my $j (0..3) { $x[$i][$j]=int rand 10; } } for my $i (0..3) { for my $j (0..3) { print $x[$i][$j]," "; } print "\n"; } exit;
    Extending this to three dimensions is trivially easy, just add another set of brackets after [$j], but then printing it gets harder. Read perllol

    HTH,
    SSF

Re: Creating multidimentional arrays dynamically
by jethro (Monsignor) on Aug 13, 2010 at 09:12 UTC
    Lets say you have ArrayofArrays x. To add $value to row 5 do this:
    push @{$x[5]}, $value;

    The nice thing: it does not matter whether row 5 existed before, it will be created when needed (this is called autovivication)

    To remove values from the end of a row you use pop

    $value= pop @{$x[5]};

    To remove the first value instead use shift:

    $value= shift @{$x[5]};

    To remove or add values into the middle of an array use splice. Do 'perldoc -f splice' on the command line to read more about that

    To access one or all values of row 5 or all rows you do this:

    #access one value in row 5 $n= $x[5][4]; #access all values in row 5 foreach $n ( @{$x[5]} ) { } #access all values in @x foreach $row ( @x ) { foreach $n ( @$row ) { }

    The syntax @$row is shorthand for @{$row} which you have seen above

Re: Creating multidimentional arrays dynamically
by JavaFan (Canon) on Aug 13, 2010 at 09:24 UTC
    The question what to do has already been answered.

    But I have a question for you. What makes you think you need to know the number of columns/rows in advance? Did you read anything in the documentation that suggests this? I'd like to know, because if it's poor documentation, it can be fixed. (Unlike poorly written books; they cannot be unwritten).