in reply to N-Dimensional Arrays on the fly

Here's a solution with neither eval nor recursion. In terms of efficiency, for a total of N elements created, this requires between 1N and 1.5N passes (best & worst cases I got with a fair number of tests).


Update

Minor code change - runs a bit faster.


Here's the class - substitute your own constructor, accessor and mutator methods. (You'll need to include the equivalent of $self->init in your own constructor.)

package WhiteMouse; use strict; use warnings; use constant DEFAULT_OBJECT_ARRAY_VAL => [ 0 ]; sub new { my $self = bless { %{$_[1]} }, ref($_[0]) || $_[0]; $self->i +nit; $self } sub get { $_[0]->{$_[1]} } sub set { $_[0]->{$_[1]} = $_[2] } sub init { my $self = shift; my $ra_dim = $self->get('object_array_dim'); my $ra_val = $self->get('object_array_val') || DEFAULT_OBJECT_ARRA +Y_VAL; my $use_single_value = ! $#{$ra_val}; my $ra_obj = []; my $ra_p = $ra_obj; my @todo = (); my $dim_l = $#{$ra_dim}; for (my $i = 0; $i <= $dim_l; ++$i) { @{$ra_p}[0 .. $ra_dim->[$i] - 1] = map {[]} (1 .. $ra_dim->[$i +]) unless $i == $dim_l; for (my $j = 0; $j < $ra_dim->[$i]; ++$j) { if ($i == $dim_l) { $ra_p->[$j] = $use_single_value ? $ra_val->[0] : shift(@$ra_val) || DEFA +ULT_OBJECT_ARRAY_VAL; } else { push @todo, [$ra_p->[$j], $i]; } } ($ra_p, $i) = @{shift @todo} if @todo; } $self->set(object_array => $ra_obj); }

Update

Removed the line

next if $i == $dim_l && @todo;

which was after the line

($ra_p, $i) = @{shift @todo} if @todo;

because


I tested it like this:

use strict; use warnings; use Data::Dumper; my $ra_dim = [ qw( 2 2 ) ]; my $ra_val = [ qw( A B C D E F G H I J K L) ]; print 'DIM: ', "@$ra_dim\n"; print 'VAL: ', "@$ra_val\n"; my $ro_pandim1 = WhiteMouse->new({ object_array_dim => $ra_dim, object_array_val => $ra_val, }); my $ro_pandim2 = WhiteMouse->new({ object_array_dim => $ra_dim, object_array_val => [ 'XXXX' ], }); my $ro_pandim3 = WhiteMouse->new({ object_array_dim => $ra_dim, }); print "=======================================\n"; print Dumper $ro_pandim1->get('object_array'); print Dumper $ro_pandim2->get('object_array'); print Dumper $ro_pandim3->get('object_array'); print "=======================================\n";

Note the different calling methods:

Regards,

PN5