Roy Johnson has asked for the wisdom of the Perl Monks concerning the following question:

In response to Initializing multidimensional arrays, I wanted to come up with a general solution: given an initialization value and the dimensions, initialize an array. Here's what I came up with:
use Algorithm::Loops 'NestedLoops'; use Data::Dumper; sub init_arr { my ($val, @dims) = @_; my $arr; NestedLoops( [map [0..$_-1], @dims], sub {my $r = \$arr; map {$r=\ +(($$r)->[$_])} @_; $$r=$val} ); $arr; } print Dumper (init_arr('hi',3,2,1));
It works, but it seems like there should be a way to track my current position in $arr. I'm having to follow the chain of refs through all dimensions on each iteration. How would you do it?

Update: I'd really like to see an example using Algorithm::Loops 'NestedLoops'. This isn't something I'm doing because I need the task accomplished, it's a learning thing.


Caution: Contents may have been coded under pressure.

Replies are listed 'Best First'.
Re: General Solution: initializing multidimensional arrays
by BrowserUk (Patriarch) on Jun 01, 2005 at 13:59 UTC
    How would you do it?

    Recursively.

    #! perl -slw use strict; use Data::Dumper::SLC; sub multiDimInit { my( $value, $dim ) = ( shift, shift ); return $value unless $dim; return map{ [ multiDimInit( $value, @_ ) ] } 1 .. $dim; } my @multi = multiDimInit( 12345, 2, 2, 2, 2 ); Dump \@multi, 80, *STDOUT; __END__ P:\test>462436 [ [ [ [ [ '12345', ], [ '12345', ], ], [ [ '12345', ], [ '1234 +5', ], ], ], [ [ [ '12345', ], [ '12345', ], ], [ [ '12345', ], [ '1234 +5', ], ], ], ], [ [ [ [ '12345', ], [ '12345', ], ], [ [ '12345', ], [ '1234 +5', ], ], ], [ [ [ '12345', ], [ '12345', ], ], [ [ '12345', ], [ '1234 +5', ], ], ], ], ]

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Your base case was a level off: your sub guarantees that the bottom level arrays will have one element each. A correction:
      sub multiDimInit { my( $value, $dim ) = ( shift, shift ); return ($value) x $dim unless @_; return map [multiDimInit( $value, @_ )], 1 .. $dim; }

      Caution: Contents may have been coded under pressure.

        Much better++


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      That's so funny - I was going to post the exact same response. :-)

      • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
      • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
Re: General Solution: initializing multidimensional arrays
by merlyn (Sage) on Jun 01, 2005 at 14:01 UTC
    How would you do it?
    Since you asked, my answer is "I don't".

    I've written a lot of Perl code over the many years. Rarely have I needed to "initialize" anything. Maybe it's the class of problems I solve, but I generally just let autoviv take care of fleshing out my arrays and hashes as I need them.

    Letting undef stand in for either an empty string or the zero value is amazingly handy.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Bit of a "forest/trees" issue. Initialization is not the goal, it is merely a scenario. The goal is to iterate over an n-dimensional (sub-)array. And preferably with Algorithm::Loops NestedLoops. For a more palatable scenario, say I wanted A::L NL to give me an iterator.

      Caution: Contents may have been coded under pressure.