views:

760

answers:

5

Handling two dimensional arrays in Perl is giving me a headache. Anyway, the following is my question:

I have a loop which pushes an array, say @twoOneArray, into another array, say @twoDimArray, and then is reset before the next iteration of loop begins and then again is pushed into @twoDimArray with new set of values. When I print this @twoDimArray using either:

print Dumper \@twoDimArray;

it gives output

OUTPUT

$VAR1 = [

      [

        'BB',

        'AA',

        'AA'
       ],
       $VAR1->[0],
       $VAR1->[0],
       $VAR1->[0]
     ];

or using loops

for (my $i=0; $i<4; $i++){
    for (my $j=0; $j<4; $j++){
         print "$twoDimArray[$i][$j] \n";
    }
}

the data gets duplicated.

OUTPUT

Row=0 BB AA AA

Row=1 BB AA AA

Row=2 BB AA AA

Row=3 BB AA AA

and so on....

I cant figure out why the both the output ways are going wrong. If I print @twoDimArray everytime (before moving to next iteration of loop, i.e. after using push function) @twoOneArray is inserted, then the values seem to be fine and not repeat themselves, but printing it in a single go seems to give the above error. Similar question has been asked here but I am not sure if it makes sense to me. Any suggestions?

Code to build 2D array:

for ($k = 1; $k <= $counter; $k++){
        @twoOneArray = (); #reset it when loop starts again
        for ($j = 0; $j <= $colsInArray; $j++){
        #do stuff to create @twoOneDim
        }
        push @twoDimArray, \@twoOneArray;
        #if I print @twoDimArray if prints fine, with the exact values intact
}

print Dumper \@twoDimArray; #if I print it here it messes up
print "\n";
A: 

Check this previous question: http://stackoverflow.com/questions/1112988/printint-2-dim-array-in-perl

Salty
@Salty: I mentioned that link in my question and have said 'I am not sure if that makes to me'
shubster
Sorry about that. I clicked the link but then switched to another tab and confused myself. :P
Salty
+9  A: 

The output of Data::Dumper tells me that your problem is not printing the array. Data::Dumper doesn't never lies (or only rarely).

Please show us the code you used to build the array. I'm sure that error is in that code somewhere.

UPDATE:

Now that you added the code that builds up the array, I see that you've fallen into an evil trap: You are adding the reference to @twoOneArray to your "outer" array. But the reference will always be the same each time through your loop. Change your code like this:

for ($k = 1; $k <= $counter; $k++){
        my @twoOneArray; # REALLY reset it when loop starts again
        for ($j = 0; $j <= $colsInArray; $j++){
            #do stuff to create @twoOneDim
        }
        push @twoDimArray, \@twoOneArray;
}

.. and it should work.

innaM
@Manni: Code added.
shubster
@Manni: I could have never thought of that error. Thanks a ton for highlighting it. I had been de-bugging this forever now. You helped me a lot and made my day! Thanks again :)
shubster
A: 

If you want an array of arrays, you should be pushing array references, e.g.

my @a = qw(1 2 3 4 5 6 7 8);
my @b = qw(a b c d e f g h);
my @aOfa;

push(@aOfa, \@a);
push(@aOfa, \@b);
xcramps
The OP is pushing array references, look at the Data::Dumper output.
derobert
+4  A: 

You've done something like this:

@a = (1, 2, 3);
push @b, \@a;

@a = (2, 3, 4);
push @b, \@a;

# ...

The problem is that you're pushing on @b a reference to @a. All the references point to the same @a. Data::Dumper is telling you that with its $VAR->[0] thing.

You need to do something like:

$a = [ 1, 2, 3 ];
push @b, $a;

$a = [ 2, 3, 4] ;
push @b, $a;

# ....

This way, the [ ... ] arrayref syntax will make a new referenced array each time.

I suggest a careful reading of perlreftut and perlref.

edit: I see you've posted your code, and yep, you're doing my example broken code. Change to using [ ... ] syntax and you'll be fine.

derobert
+4  A: 

Your question has been answered adequately by others. I would add that the output from Data::Dumper is useful in spotting such problems: the [1] element of your array is dumped as $VAR1->[0] -- in other words, it is a reference to the same underlying data values stored in the [0] element.

FM