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

Hi,

I have an array, of which some elements are scalars and some of which are array refs. There are a lot of fields, and i don't know definitely which column will have a scalar and which will have array refs until I parse it in.

My question is: Is there a module that will multiplex a datastructure like this out to multiple rows, one for each combination of elements in the array? For example, if I have:

( static1, (ar1, ar2), static2, (ar3, ar4, ar5) )

I want it to print:

static1, ar1, static2, ar3
static1, ar1, static2, ar4
static1, ar1, static2, ar5
static1, ar2, static2, ar3
static1, ar2, static2, ar4
static1, ar2, static2, ar5


Now, I think I can be clever and use the ideas in MJD 'Higher Order Perl' and keep an agenda/stack of partially processed lines that shifts off an element, expands the first array it comes to into N arrays, not modifying the elements behind it, and putting it back on the stack. If an element in the stack has no array refs as element, just return it.

But I don't want to reinvent the wheel, and I think this may have already been done -- I just don't know what keywords to use to search for a solution. Does anybody know if a solution to this already exists as a module, and how would I phrase the problem best in a common language that people would understand?

Thanks, Matt

UPDATE: Thank you both ikegami and Fletch! I'll likely implement ikegami's, but will play with Fletch's solution.

Replies are listed 'Best First'.
Re: Multiplexing array of arrays?
by Fletch (Bishop) on Feb 02, 2010 at 18:30 UTC

    Module schmodule, you can do it with just the builtin glob:

    $ perl -le 'print join( "\n", glob( "static1,ar{1,2},static2,ar{3,4,5} +" ) )' static1,ar1,static2,ar3 static1,ar1,static2,ar4 static1,ar1,static2,ar5 static1,ar2,static2,ar3 static1,ar2,static2,ar4 static1,ar2,static2,ar5

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

      A more generic solution:

      my @spec = ( 'static1', [ 'ar1', 'ar2' ], 'static2', [ 'ar3', 'ar4', 'ar5' ], ); my $pat = join quotemeta(', '), map { ref($_) ? '{'.join(',', map quotemeta, @$_).'}' : quotemeta($_) } @spec; print "$_\n" for glob($pat);
      Hey, this is really interesting would you please shed more light on how glob is used this way??

      From what I make, it looks like you are matching but what tricks me is the {} so I can be wrong...


      Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
        glob is a list generator. An entry will be generated for each value of a list in curlies
        $ perl -le'print for glob "{a,b,c}{d,e,f}"' ad ae af bd be bf cd ce cf

        A shell example:

        cp file{,.bk}
        is the same as
        cp file file.bk
Re: Multiplexing array of arrays?
by ikegami (Patriarch) on Feb 02, 2010 at 18:28 UTC
    use Algorithm::Loops qw( NestedLoops ); my @spec = ( [ 'static1' ], [ 'ar1', 'ar2' ], [ 'static2' ], [ 'ar3', 'ar4', 'ar5' ], ); NestedLoops(\@spec, sub { print(join(', ', @_), "\n"); });

    Or closer to what you have:

    use Algorithm::Loops qw( NestedLoops ); my @spec = map { ref($_) ? $_ : [$_] } ( 'static1', [ 'ar1', 'ar2' ], 'static2', [ 'ar3', 'ar4', 'ar5' ], ); NestedLoops(\@spec, sub { print(join(', ', @_), "\n"); });

    Update: Fixed bug.
    Update: Added alt.