views:

4860

answers:

6

Hello, I am a bit new to Perl, but here is what I want to do:

my @array2d;
while(<FILE>){
  push(@array2d[$i], $_);
}

It doesn't compile since @array2d[$i] is not an array but a scalar value. How sould I declare @array2d as an array of array?

Of course, I have no idea of how many rows I have.

+4  A: 

Have a look at perlref and perldsc to see how to make nested data structures, like arrays of arrays and hashes of hashes. Very useful stuff when you're doing Perl.

Paul Tomblin
+7  A: 

To make an array of arrays, or more accurately an array of arrayrefs, try something like this:

my @array = ();
foreach my $i ( 0 .. 10 ) {
  foreach my $j ( 0 .. 10 ) {
    push @{ $array[$i] }, $j;
  }
}

It pushes the value onto a dereferenced arrayref for you. You should be able to access an entry like this:

print $array[3][2];
gpojd
You can also access as $array[3][2] -- the arrow isn't needed between successive [n] or {key} indexes of multi-level data structures.
xdg
You're right, thanks for the info. I'm going to update the answer to reflect that.
gpojd
+2  A: 

Programming Perl (O'Reilly) starting on Page 268 covers what you're looking for.

Tim
+6  A: 

Change your "push" line to this:

push(@{$array2d[$i]}, $_);

You are basically making $array2d[$i] an array by surrounding it by the @{}... You are then able to push elements onto this array of array references.

BrianH
Good explanation. To clarify further, $array2d[$i] is an array reference. In @{$array2d[$i]}, the {} block returns the array reference and the @ sigil dereferences it as an array. I point this out to make it clear that the braces are a bare block, not a device for subverting precedence.
converter42
Thanks for clarifying my explanation - I knew that it worked, but I never knew the technical reasons behind it. Thanks!
BrianH
No, they're a dereferencing block, not a bare block. In perl -wle'{ 1 if @{;last}; print "in" } print "out"', the last sees the outer, truly bare block, not the inner block.
ysth
A: 

Another simple way is to use a hash table and use the two array indices to make a hash key:

$two_dimensional_array{"$i $j"} = $val;
Nathan Fellman
+1  A: 

There's really no difference between what you wrote and this:

@{$array2d[$i]} = <FILE>;

I can only assume you're iterating through files.

To avoid keeping track of a counter, you could do this:

...
push @array2d, [ <FILE> ];
...

That says 1) create a reference to an empty array, 2) storing all lines in FILE, 3) push it onto @array2d.

Axeman
I find this syntax really excellent. Good solution.
JSBangs