Amelio Vazquez-Reina
Amelio Vazquez-Reina

Reputation: 96350

Building and printing a multidimensional list in Perl without looping

The top answer in this post: How can I create a multidimensional array in Perl? suggests building a multi-dimensional array as follows:

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

I am wondering if there is a way of building the array more compactly and avoiding the nested loop, e.g. using something like:

my @array = ();
my @other_array = (0 ... 10);
foreach my $i ( 0 .. 10 ) {
    $array[$i] = @other_array; # This does not work in Perl
  }
}

Does Perl support any syntax like that for building multi-dimensional arrays without nested looping?

Similarly, is there a way to print the multidimensional array without (nested) looping?

Upvotes: 0

Views: 432

Answers (2)

Zaid
Zaid

Reputation: 37146

There is more than one way to do it:

Generating

push accepts LISTs

my @array;
push @{$array[$_]}, 0 .. 10 for 0 .. 10;

Alternative syntax:

my @array;
push @array, [ 0 .. 10 ] for 0 .. 10;

map eye-candy

my @array = map { [ 0 .. 10 ] } 0 .. 10;

Alternative syntax:

my @array = map [ 0 .. 10 ], 0 .. 10;

Printing

With minimal looping

print "@$_\n" for @array;

On Perl 5.10+

use feature 'say';
say "@$_" for @array;

With more formatting control

print join( ', ', @$_ ), "\n" for @array;   # "0, 1, 2, ... 9, 10"

"No loops" (The loop is hidden from you)

use Data::Dump 'dd';
dd @array;

Data::Dumper

use Data::Dumper;
print Dumper \@array;

Have a look at perldoc perllol for more details

Upvotes: 6

Joel Berger
Joel Berger

Reputation: 20280

You are close, you need a reference to the other array

my @array;  # don't need the empty list
my @other_array = (0 ... 10);
foreach my $i ( 0 .. 10 ) {
    $array[$i] = \@other_array;
    # or without a connection to the original
    $array[$i] = [ @other_array ];
    # or for a slice
    $array[$i] = [ @other_array[1..$#other_array] ];
  }
}

You can also make anonymous (unnamed) array reference directly using square braces [] around a list.

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

Edit: printing is probably easiest using the postfix for

print "@$_\n" for @array;

for numerical multidimensional arrays, you can use PDL. It has several constructors for different use cases. The one analogous to the above would be xvals. Note that PDL objects overload printing, so you can just print them out.

use PDL;
my $pdl = xvals(11, 11);
print $pdl;

Upvotes: 2

Related Questions