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

Hi Monks!

I am trying to pass a two-dimensional array through a Win32::Pipe. This basically means that I need to convert the array to a string to "write" and then unconvert it to "read". To cut down on I/O through the pipe, I'd like to do this without having to use a "for" loop on either end.

A one dimensional array is encoded like this:

$Pipe->Write( join( "\0", @Array) );

And decoded like this:

@Array = split( "\0", $Pipe->Read() );

I've tried lots of different ways to encode/decode a two-dimensional array with no success. These have included:
1) Using multiple joins and splits (I end up passing a string like "ARRAY(0x20e301c)"
2) Using a number of variations on map (including one that used pack/unpack) and either got the string in (1) or nothing.

Please help!

Replies are listed 'Best First'.
Re: Joining and splitting two dimensional arrays
by chromatic (Archbishop) on Aug 06, 2003 at 18:13 UTC

      Storable seems to just put things into a disk file, or am I missing something? I don't want to use disk if I can avoid it.

      I'm not sure how I could use YAML. I looked at the link, but it isn't clear to me exactly how it works. Is there a way to convert a standard array into YAML and then send it through the pipe? Would the pipe see the YAML type as a string type? If so, how?

      Thanks!

        From the Storable documentation:

        use Storable qw(freeze thaw); # Serializing to memory $serialized = freeze \%table; %table_clone = %{ thaw($serialized) };

        Hope this helps.

        antirice    
        The first rule of Perl club is - use Perl
        The
        ith rule of Perl club is - follow rule i - 1 for i > 1

Re: Joining and splitting two dimensional arrays
by CombatSquirrel (Hermit) on Aug 06, 2003 at 19:57 UTC
    I put together a piece of code that might help you:

    #!perl -sw my $input = [[1, 3, 4, 2], [7, 5, 3, 6], [5, 4, 2, 4]]; my $SEP = " "; my $send; sub printarray { my $arr = shift; for my $t (@$arr) { for (@$t) { print "$_ "; } print "\n"; } } sub encode { my $arr = shift; join $SEP x 2, map { join $SEP, @$_ } @$arr; } sub decode { my $in = shift; [(map { [(split $SEP, $_)] } split($SEP x 2, $in))]; } printarray($input); print "\n" x 2; $send = encode($input); print $send . "\n" x 2; $input = decode($send); printarray($input);

    It seperates the elements of one line by one separator and two consecutive lines by two separators. Note that although I embedded everything in subs (a nasty little habit of mine) the essential parts are one-liners.
    encode expects a reference to an array, decode returns an unnamed array.

    Hope this helped.
      Thank you! This looks like it would work and work well, but I have to admit that I already implemented the solution that uses freeze and thaw.
Re: Joining and splitting two dimensional arrays
by Not_a_Number (Prior) on Aug 06, 2003 at 20:12 UTC

    Just as an exercise (as I'm still trying to master 2D arrays) I thought I'd try to roll my own solution. Here it is, FWIW:

    use strict; use warnings; my @ary = ( [ 'fred', 'barney' ], [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], [ 'george', 'jane', 'elroy' ], [ 'homer' ] ); my $str = ''; for ( @ary ) { unshift @$_, $#$_; $str .= "\0" if $str; $str .= join "\0", @$_; } # And then at the other end: my @in = split /\0/, $str; my @new_ary; push @new_ary, [ splice @in, 0, shift @in ] while @in; print "@$_\n" for @new_ary;

    Comments more than welcome

    dave