Reputation: 15294
I have the code below:
@a = ((1,2,3),("test","hello"));
print @a[1]
I was expecting it to print
testhello
But it gives me 2
.
Sorry for the newbie question (Perl is a bit unnatural to me) but why does it happen and how can I get the result I want?
Upvotes: 5
Views: 5964
Reputation: 4800
Perl lists are one-dimensional only, which means (1,2,(3,4))
is automatically flattened to (1,2,3,4)
. If you want a multidimensional array, you must use references for any dimension beyond the first (which are stored in scalars).
You can get any anonymous array reference with bracket notation [1,2,3,4]
or reference an existing array with a backslash my $ref = \@somearray
.
So a construct such as my $aref = [1,2,[3,4]]
is an array reference in which the first element of the referenced array is 1, the second element is 2, and the third element is another array reference.
(I find when working with multidimensional arrays, that it's less confusing just to use references even for the first dimension, but my @array = (1,2,[3,4])
is fine too.)
By the way, when you stringify a perl reference, you get some gibberish indicating the type of reference and the memory location, like "ARRAY(0x7f977b02ac58)".
Dereference an array reference to an array with @
, or get a specific element of the reference with ->
.
Example:
my $ref = ['A','B',['C','D']];
print $ref; # prints ARRAY(0x001)
print join ',', @{$ref}; # prints A,B,ARRAY(0x002)
print join ',', @$ref; # prints A,B,ARRAY(0x002) (shortcut for above)
print $ref->[0]; # prints A
print $ref->[1]; # prints B
print $ref->[2]; # prints ARRAY(0x002)
print $ref->[2]->[0]; # prints C
print $ref->[2][0]; # prints C (shortcut for above)
print $ref->[2][1] # prints D
print join ',', @{$ref->[2]}; # prints C,D
Upvotes: 6
Reputation: 26397
The way Perl constructs @a
is such that it is equivalent to your writing,
@a = (1,2,3,"test","hello");
And that is why when you ask for the value at index 1
by writing @a[1]
(really should be $a[1]
), you get 2
. To demonstrate this, if you were to do the following,
use strict;
use warnings;
my @a = ((1,2,3), ("test","hello"));
my @b = (1,2,3,"test","hello");
print "@a\n";
print "@b\n";
Both print the same line,
1 2 3 test hello
1 2 3 test hello
What you want is to create anonymous arrays within your array - something like this,
my @c = ([1,2,3], ["test","hello"]);
Then if you write the following,
use Data::Dumper;
print Dumper $c[1];
You will see this printed,
$VAR1 = [
'test',
'hello'
];
Upvotes: 6
Reputation: 6571
I think you're after an array of arrays. So, you need to create an array of array references by using square brackets, like this:
@a = ([1,2,3],["test","hello"]);
Then you can print the second array as follows:
print @{$a[1]};
Which will give you the output you were expecting: testhello
Upvotes: 3