Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

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

Comment on Iterator for multidimensional arrays
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."
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 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 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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://153873]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (4)
As of 2014-07-12 00:27 GMT
Find Nodes?
    Voting Booth?

    When choosing user names for websites, I prefer to use:

    Results (237 votes), past polls