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

Given a list of array refs like:

my @list = ([0..1], [2..4], [5..8]);

I want to generate all possible sets (triples in this case) each set containing one element of each array :

0,2,5 1,2,5 0,3,5 1,3,5 ...

I spent a day trying to no avail. I wonder if somebody already solved this problem.

Replies are listed 'Best First'.
Re: Combinations of multiple arrays
by ikegami (Patriarch) on Jan 15, 2010 at 06:05 UTC
    Algorithm::Loops's NestedLoops will do the trick:
    use Algorithm::Loops qw( NestedLoops ); NestedLoops(\@list, sub { print(join(',', @_), "\n"); }, );
    Or as an iterator:
    use Algorithm::Loops qw( NestedLoops ); my $i = NestedLoops(\@list); while (my @set = $i->()) { print(join(',', @set), "\n"); }

    Update: Fixed capitalization typo mentioned in reply.

      Notice that there is a mistake in above code. It should be NestedLoops with a CAPITAL L.
      #/usr/bin/perl use Algorithm::Loops qw( NestedLoops ); my @list = ( [12,13,14,15], [6000,6001,6002,3150,3152], ['314456 C', '314484 D']); my $i = NestedLoops(\@list); while (my @set = $i->()) { print(join(',', @set), "\n"); }

        Thanks, fixed.

Re: Combinations of multiple arrays
by ikegami (Patriarch) on Jan 15, 2010 at 06:15 UTC

    glob will also do the trick

    my $glob = join ',', map '{'.join(',', @$_).'}', @list; while (my $s = glob($glob)) { print "$s\n"; }
Re: Combinations of multiple arrays
by fod (Friar) on Jan 15, 2010 at 05:18 UTC
Re: Combinations of multiple arrays
by tybalt89 (Monsignor) on Sep 08, 2020 at 22:48 UTC

    Simple map-in-map algorithm.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=817521 use warnings; my @list = ([0..1], [2..4], [5..8]); my @sets = []; for my $eacharray ( @list ) { @sets = map { my @prev = @$_; map [ @prev, $_ ], @$eacharray } @sets +; } use Data::Dump 'dd'; dd @sets;

      Inspiration struck after 10 years? ;-)

      -Thomas
      "Excuse me for butting in, but I'm interrupt-driven..."
Re: Combinations of multiple arrays
by Anonymous Monk on Jan 15, 2010 at 05:10 UTC
Re: Combinations of multiple arrays
by Fletch (Bishop) on Jan 15, 2010 at 14:09 UTC
    $ perl -le 'open( my $ghci, "|-", "ghci" );print $ghci q{[ (x,y,z) | x + <- [0..1], y <- [2..4], z <- [5..8] ]}, "\n";' GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Loading package ffi-1.0 ... linking ... done. Prelude> [(0,2,5),(0,2,6),(0,2,7),(0,2,8),(0,3,5),(0,3,6),(0,3,7),(0,3 +,8),(0,4,5),(0,4,6),(0,4,7),(0,4,8),(1,2,5),(1,2,6),(1,2,7),(1,2,8),( +1,3,5),(1,3,6),(1,3,7),(1,3,8),(1,4,5),(1,4,6),(1,4,7),(1,4,8)] Prelude> Prelude> Leaving GHCi.

    </snark>

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Combinations of multiple arrays
by doug (Pilgrim) on Jan 15, 2010 at 21:19 UTC

    Does this do what you want?

    #!/usr/bin/perl use strict; use warnings; use 5.010; sub numbers($) { my $numbers = shift; $numbers =~ s/[\00-\32]+//; my @list; foreach my $chunk ( split ',', $numbers ) { given ( $chunk ) { when ( /^\d$/ ) { push @list, $_; } when ( /^(\d+)\.\.(\d+)$/ ) { push @list, $1..$2; } default { die "what is '$_'?"; } } } @list; } sub iterator($) { my @numbers = numbers( shift ); sub { my @args = @_ or return @numbers; my @output; foreach my $n ( @numbers ) { push @output, map { "$_,$n" } @args; } @output; }; } my @output; foreach my $iterator ( map { iterator $_ } <DATA> ) { @output = &$iterator( @output ); } print map { "$_\n" } @output; __DATA__ 0,1 2..4 5..8