开发者

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

开发者 https://www.devze.com 2023-03-14 05:07 出处:网络
I was creating a multi-dimensional array this way: #!/usr/bin/perl use warnings; use strict; my @a1 = (1, 2);

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 w开发者_运维技巧ay in Perl?


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).


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.


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.


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);


Inner arrays should be scalar references in the outer one:

my @a2 = (\@a1,3); # first element is a reference to a1
print ${$a2[0]}[1]; # print second element of inner array


This is a simple example of a 2D array as ref:

my $AoA = undef;
for(my $i=0; $i<3; $i++) {
   for(my $j=0; $j<3; $j++) {
      $AoA->[$i]->[$j] = rand(); # Assign some value
   }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消