Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Iterator for multidimensional arrays

by jcupp (Acolyte)
on Mar 24, 2002 at 09:02 UTC ( #153873=perlquestion: print w/replies, xml ) Need Help??
jcupp has asked for the wisdom of the Perl Monks concerning the following question:

n=1 is easy, but what's a generic solution when n=whatever? A few ways I can iterate through a collection... can any of these be applied to the solution of multi-d arrays? It should hit every possible combination along the way...

1. traditional procedural: for loops
2. OO: while ($item = $collection->next)...
3. Stack: while (shift @collection)...
4. That Ruby thing with 'yield' (passing a closure)
5. returning a closure which acts as a next: while ($fetch->() )
6. can't think of a six...

Replies are listed 'Best First'.
•Re: Iterator for multidimensional arrays
by merlyn (Sage) on Mar 24, 2002 at 13:35 UTC
    Since Perl doesn't have "multidimensional arrays", it's a "what if pigs could fly" question anyway.

    When you understand that Perl arrays cannot hold other arrays, but rather references to arrays, the solutions naturally start occurring. But thinking of them as "multidimensional arrays" is akin to Kirk claiming that Kahn was "thinking in two dimensions" during the final battle of Wrath of Kahn. In other words, by not seeing it as it is, you misunderstand the possibilities.

    -- Randal L. Schwartz, Perl hacker

Re: Iterator for multidimensional arrays
by Masem (Monsignor) on Mar 24, 2002 at 13:35 UTC
    Another possibility would be to have a single iteration loop from 0 to N1 * N2 * N3 *..., and on, and using mod functions on the index to figure out the positions within the array.

    Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
    "I can see my house from here!"
    It's not what you know, but knowing how to find it if you don't know that's important

Re: Iterator for multidimensional arrays
by rinceWind (Monsignor) on Mar 24, 2002 at 10:44 UTC
    I can think of a 6.

    How about recursion? You iterate the first dimension, calling yourself with its arrayref.

Re: Iterator for multidimensional arrays
by shotgunefx (Parson) on Mar 24, 2002 at 09:19 UTC
    A little clarification on "every possible combination" would help (me anyway).
    Do you mean... my @aoa = (
    [ 1,2],
    [ a,b],
    [ A,B],



    "To be civilized is to deny one's nature."
      Almost. A call ->next would return an array of the current 'state' of the system:
        If you want the list generated at once, you could use the following snippet by merlyn. If you want an iterative solution, you could use the following. A benefit being that it should work in relatively constant time no matter how big the arrays are.
        my @aoa = ( [1,2], ['a','b','c','d'], ['A','B','C'], ); my $iter = make_aoa_iterative(@aoa); while (my @els = $iter->() ){ print @els,"\n"; } sub make_aoa_iterative { my @arefs = @_; my @arrayindexes = (); foreach (@arefs){ push @arrayindexes,[$_,0,$#{$_}]; } return sub { return if $arrayindexes[0]->[1] > $arrayindexes[0]->[2]; my @els = map { $_->[0]->[ $_->[1]] } @arrayindexes; # Check for out of bounds.... $arrayindexes[$#arrayindexes]->[1]++; for (my $i = $#arrayindexes; $i > 0; $i--){ if ($arrayindexes[$i]->[1] > $arrayindexes[$i]->[2 +]){ $arrayindexes[$i]->[1] = 0; $arrayindexes[$i-1]->[1]++; }else{ last; } } return @els; }; }

        I'm formal-math challenged. Is this formally a permutation? If someone could clarify, I'd appreciate it.


        "To be civilized is to deny one's nature."

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://153873]
Approved by root
[marto]: good morning all

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2018-02-20 10:10 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (268 votes). Check out past polls.