Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a multi-dimensional array in perl?

Tags:

perl

I was creating a multi-dimensional array this way:

#!/usr/bin/perl
use warnings;
use strict;

my @a1 = (1, 2);
my @a2 = (@a1, 3);

But it turns out that I still got a one-dimensional array...

What's the right way in Perl?

like image 300
Je Rog Avatar asked Jun 21 '11 13:06

Je Rog


4 Answers

You get a one-dimensional array because the array @a1 is expanded inside the parentheses. So, assuming:

my @a1 = (1, 2);
my @a2 = (@a1, 3);

Then your second statement is equivalent to my @a2 = (1,2,3);.

When creating a multi-dimensional array, you have a few choices:

  1. Direct assignment of each value
  2. Dereferencing an existing array
  3. Inserting a reference

The first option is basically $array[0][0] = 1; and is not very exciting.

The second is doing this: my @a2 = (\@a1, 3);. Note that this makes a reference to the namespace for the array @a1, so if you later change @a1, the values inside @a2 will also change. It is not always a recommended option.

A variation of the second option is doing this: my @a2 = ([1,2], 3);. The brackets will create an anonymous array, which has no namespace, only a memory address, and will only exist inside @a2.

The third option, a bit more obscure, is doing this: my $a1 = [1,2]; my @a2 = ($a1, 3);. It will do exactly the same thing as 2, only the array reference is already in a scalar variable, called $a1.

Note the difference between () and [] when assigning to arrays. Brackets [] create an anonymous array, which returns an array reference as a scalar value (for example, that can be held by $a1, or $a2[0]).

Parentheses, on the other hand, do nothing at all really, except change the precedence of operators.

Consider this piece of code:

my @a2 = 1, 2, 3;
print "@a2";

This will print 1. If you use warnings, you will also get a warning such as: Useless use of a constant in void context. Basically, this happens:

my @a2 = 1;
2, 3;

Because commas (,) have a lower precedence than equal sign =. (See "Operator Precedence and Associativity" in perldoc perlop.)

Parentheses simply negate the default precedence of = and ,, and group 1,2,3 together in a list, which is then passed to @a2.

So, in short, brackets, [], have some magic in them: They create anonymous arrays. Parentheses, (), just change precedence, much like in math.

There is much to read in the documentation. Someone here once showed me a very good link for dereferencing, but I don't recall what it was. In perldoc perlreftut you will find a basic tutorial on references. And in perldoc perldsc you will find documentation on data structures (thanks Oesor for reminding me).

like image 112
TLP Avatar answered Oct 19 '22 15:10

TLP


I would propose to work through perlreftut, perldsc and perllol, preferably in the same day and preferably using Data::Dumper to print data structures.

The tutorials complement each other and I think they would take better effect together. Visualizing data structures helped me a lot to believe they actually work (seriously) and to see my mistakes.

like image 38
Roman Grazhdan Avatar answered Oct 19 '22 16:10

Roman Grazhdan


Arrays contain scalars, so you need to add a reference.

my @a1 = (1,2);
my @a2 = (\@a1, ,3);

You'll want to read http://perldoc.perl.org/perldsc.html.

like image 4
Oesor Avatar answered Oct 19 '22 14:10

Oesor


The most important thing to understand about all data structures in Perl--including multidimensional arrays--is that even though they might appear otherwise, Perl @ARRAY s and %HASH es are all internally one-dimensional. They can hold only scalar values (meaning a string, number, or a reference). They cannot directly contain other arrays or hashes, but instead contain references to other arrays or hashes.

Now, because the top level contains only references, if you try to print out your array in with a simple print() function, you'll get something that doesn't look very nice, like this:

    @AoA = ( [2, 3], [4, 5, 7], [0] );
    print $AoA[1][2];
    7
    print @AoA;
    ARRAY(0x83c38)ARRAY(0x8b194)ARRAY(0x8b1d0)

That's because Perl doesn't (ever) implicitly dereference your variables. If you want to get at the thing a reference is referring to, then you have to do this yourself using either prefix typing indicators, like ${$blah} , @{$blah} , @{$blah[$i]} , or else postfix pointer arrows, like $a->[3] , $h->{fred} , or even $ob->method()->[3]

Source: perldoc


Now coming to your question. Here's your code:

my @a1 = (1,2);
my @a2 = (@a1,3);

Notice that the arrays contain scalar values. So you have to use reference and you can add a reference by using the \ keyword before an array's name which is to be referenced.

Like this:

my @a2 = (\@a1, ,3);
like image 2
Chankey Pathak Avatar answered Oct 19 '22 14:10

Chankey Pathak