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

Hi,

I have a query regarding creating and accessing elements of a 3-D Array. Below is a code for 3D array. It has three sheets of three columns and three rows each. It is made by making a column array of 3 elements. This column array is pushed inside 3 row arrays. And these 3 row arrays are pushed inside a sheet array

my $col; my @col; my $row; my @row; my $sheet; my @sheet; for($col = 0; $col < 3; $col++) { push @col, "0";} for($row = 0; $row < 3; $row++) { push @row, [@col];} for($sheet = 0; $sheet < 3; $sheet++){push @sheet, [@row];} $sheet[0][1][2] = 5; for($col = 0; $col < 3; $col++) { for($row = 0; $row < 3; $row++) { for($sheet = 0; $sheet < 3; $sheet++){ print "sheet=$sheet,row=$row,col=$col,$sheet[$sheet][$row][$col]\n"; } } }

Expected output is - all elements containing "0"'s inside them, except for $sheet[0][1][2] element, which has "5". But My output is showing three elements, $sheet[0][1][2], $sheet[1][1][2], $sheet[2][1][2] having 5 in them.

Below is full output

sheet = 0, row = 0, col = 0, 0 sheet = 1, row = 0, col = 0, 0 sheet = 2, row = 0, col = 0, 0 sheet = 0, row = 1, col = 0, 0 sheet = 1, row = 1, col = 0, 0 sheet = 2, row = 1, col = 0, 0 sheet = 0, row = 2, col = 0, 0 sheet = 1, row = 2, col = 0, 0 sheet = 2, row = 2, col = 0, 0 sheet = 0, row = 0, col = 1, 0 sheet = 1, row = 0, col = 1, 0 sheet = 2, row = 0, col = 1, 0 sheet = 0, row = 1, col = 1, 0 sheet = 1, row = 1, col = 1, 0 sheet = 2, row = 1, col = 1, 0 sheet = 0, row = 2, col = 1, 0 sheet = 1, row = 2, col = 1, 0 sheet = 2, row = 2, col = 1, 0 sheet = 0, row = 0, col = 2, 0 sheet = 1, row = 0, col = 2, 0 sheet = 2, row = 0, col = 2, 0 sheet = 0, row = 1, col = 2, 5 sheet = 1, row = 1, col = 2, 5 sheet = 2, row = 1, col = 2, 5 sheet = 0, row = 2, col = 2, 0 sheet = 1, row = 2, col = 2, 0 sheet = 2, row = 2, col = 2, 0

My understanding of making 3-D arrays is not clear. Can any one explain the concept of 3-D arrays, from this example ?

Thanks

Chak

(forgot my login details..)

Replies are listed 'Best First'.
Re: Creating and Accessing 3-D array
by BrowserUk (Patriarch) on Feb 06, 2011 at 11:26 UTC

    If you used Data::Dump (or Data::Dumper) to display your datastructure, the reason becomes clear:

    #! perl -slw use strict; use Data::Dump qw[ pp ]; my $col; my @col; my $row; my @row; my $sheet; my @sheet; for($col = 0; $col < 3; $col++) { push @col, "0";} for($row = 0; $row < 3; $row++) { push @row, [@col];} for($sheet = 0; $sheet < 3; $sheet++){push @sheet, [@row];} $sheet[0][1][2] = 5; pp \@sheet; __END__ c:\test>junk38 do { my $a = [ [[0, 0, 0], [0, 0, 5], [0, 0, 0]], ['fix', 'fix', 'fix'], ['fix', 'fix', 'fix'], ]; $a->[1][0] = $a->[0][0]; $a->[1][1] = $a->[0][1]; $a->[1][2] = $a->[0][2]; $a->[2][0] = $a->[0][0]; $a->[2][1] = $a->[0][1]; $a->[2][2] = $a->[0][2]; $a; }

    The reason is this line:

    for($sheet = 0; $sheet < 3; $sheet++){push @sheet, [@row];}

    The [@row] does a deep copy of the contents of @row, but a shallow copy of the things contained within those contents. Hence, the same arrays appear as as subarrays of the higher levels. (That's not a good description, but the best I could come up with.)

    Perhaps this corrected code will explain things better:

    #! perl -slw use strict; use Data::Dump qw[ pp ]; my $col; my @col; my $row; my @row; my $sheet; my @sheet; for($col = 0; $col < 3; $col++) { push @col, "0";} for($row = 0; $row < 3; $row++) { push @row, [@col];} for($sheet = 0; $sheet < 3; $sheet++){ push @sheet, [ map [ @$_ ], @row ]; } $sheet[0][1][2] = 5; pp \@sheet; __END__ c:\test>junk38 [ [[0, 0, 0], [0, 0, 5], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], ]

    And for reference, here's how I would initialise that construct:

    #! perl -slw use strict; use Data::Dump qw[ pp ]; my @sheets = map { [ map { [ ( 0 ) x 3 ] } 1 .. 3 ] } 1 .. 3; $sheets[0][1][2] = 5; pp \@sheets; __END__ c:\test>junk38 [ [[0, 0, 0], [0, 0, 5], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], ]

    Which I find more captures the operation and therefore easier to follow, but others might not agree.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thanks

      by the way, I loved your quotes !!

      Chak

Re: Creating and Accessing 3-D array
by ikegami (Patriarch) on Feb 06, 2011 at 11:29 UTC

    How many row arrays do you create in total? 3. How many rows do you want? 9, 3 per sheet. Do you see the problem?

    Another hint would be that your loop structure for populating the array is different than your loop structure for getting from the array, yet you are looping over the same array. How can that be?

    Fix:

    for my $sheet (1..3) { my @sheet; for my $row (1..3) { my @row; for my $col (1..3) { push @col, 0; } push @sheet, \@row; } push @sheets, \@sheet; }

    Thanks to autovivification, this can actually be simplified.

    for my $sheet (1..3) { for my $row (1..3) { for my $col (1..3) { $sheets[$sheet][$row][$col] = 0; } } }

      Yes, I figured out my mistake.

      Autovivification is great tool. I did it that way (lazy me :-))

      In my opinion, autovivification should not be taught to a beginner. It makes creating multidimentional arrays so simple that, lazy people like me will never study data structures chapter .. :-)

      Thanks

      Chak

      ---

      Laziness is the mother of invention (My philosophy)

        The equivalent without autovivification of the snippet using autovivification is

        ( ( $sheets[$sheet] //= [] )->[$row] //= [] )->[$col] = 0;

        Your choice.

Re: Creating and Accessing 3-D array
by locked_user sundialsvc4 (Abbot) on Feb 07, 2011 at 17:57 UTC

    If your specific performance requirements, etc., will allow it, I like to look upon tasks like this one in the most abstract way possible.   For instance, creating (or using from CPAN) a class that accepts a list as the “key” under which data may be stored.   Such that it does not matter how long the list (how many “dimensions” there are...)

    A crucial consideration will be:   do you, or do you not, need to iterate through the stored data’s “dimensions.”   Another will be, is the data “sparse,” and is the dimensional space in which it is stored of a fixed or known shape and size.   Earlier programming languages had nothing more sophisticated than “multi-dimensional arrays” and maybe malloc(), obliging you to think almost-immediately (and very, very physically) about how you were going to store the data.   Perl and its brethren are very different in this regard, and it is very desirable to look for ways to express your problem so as to exploit these differences.