Syntactic Confectionery Delight PerlMonks

### Iterator for multidimensional arrays

by jcupp (Acolyte)
 on Mar 24, 2002 at 09:02 UTC 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...
```
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.

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 - mneylon-pm@masemware.com || "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],
);

1
1a
1aA
1aB
1b
1bA
1bB

-Lee

"To be civilized is to deny one's nature."
Almost. A call ->next would return an array of the current 'state' of the system:
```(1,a,A)
(1,a,B)
(1,b,A)
(1,b,B)
(2,a,A)
(2,a,B)
(2,b,A)
(2,b,B)```
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;

};
}

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

-Lee

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

Create A New User
Node Status?
node history
Node Type: perlquestion [id://153873]
Approved by root
help
Chatterbox?
 [choroba]: it depends. Give more details, please [thepkd]: i used a series of {}'s but it dont work [choroba]: You need square brackets for arrays [GotToBTru]: you can certainly construct a single expression to access any part of the data structure, without using temp variables. but you might make it easier on yourself and any other poor soul who has to understand your code if you do [thepkd]: to dereference i mean LanX .oO( oh tempz, oh moretz) [thepkd]: @GotToBTru Sure. But. choroba waits

How do I use this? | Other CB clients
Other Users?
As of 2016-12-06 13:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
On a regular basis, I'm most likely to spy upon:

Results (104 votes). Check out past polls.