A wee implementation of Haskell's zip() in perl (also available via Language::Functional). Update - now maintains list order.
sub zip { my($l1, $l2) = @_; die "zip(): expects two ARRAY refs\n" if ref($l1) ne 'ARRAY' or ref($l2) ne 'ARRAY'; my %ret; @ret{ @$l1 } = @$l2; return map { $_ => $ret{$_} } @$l1; }

Replies are listed 'Best First'.
Re: a little zip()
by jmcnamara (Monsignor) on Apr 10, 2003 at 15:30 UTC

    Here is a variation that maintains order. I've used your code structure and syntax:
    sub zip2 { my($l1, $l2) = @_; die "zip(): expects two ARRAY refs\n" if ref($l1) ne 'ARRAY' or ref($l2) ne 'ARRAY'; return (@$l1, @$l2)[map {$_, $_+@$l1} 0 .. $#$l1]; }

    --
    John.

Re: a little zip()
by DrHyde (Prior) on Apr 25, 2003 at 12:52 UTC
    Here's one which zip()s an arbitrary number of arrays. If any of the arrays don't have enough elements, we pad with the empty string, cos that's what I needed at the time. Changing it to emit undefs would be trivial:
    sub zipn { local $[ = 0; [ map { my $index = $_; map { defined($_[$_][$index]) ? $_[$_][$index] : '' } 0..$#_ } 0 .. maximum(map { $#{$_[$_]} } 0..$#_) ] } sub maximum { local $[ = 0; ($#_ == 1) ? ( ($_[0] >= $_[1]) ? $_[0] : $_[1] ) : maximum(maximum($_[0], $_[1]), @_[2..$#_]); }
    Call it like so:
    zipn([1,2,3], [4,5,6], [7,8,9,10])
    and it'll return this:
    [1,4,7,2,5,8,3,6,9,'','',10]
    That maximum() function is a bit silly, getting rid of the recursion would make it way more efficient, but I firmly believe that "to recurse is divine".
Re: a little zip()
by diotalevi (Canon) on Apr 10, 2003 at 15:25 UTC

    How about returning a reference instead? Its lighter weight and can actually be treated as a hash without having to be assigned into one. Or is that part of the meaning of zip() - to return an interleaved list?

      Or is that part of the meaning of zip() - to return an interleaved list?
      Yup, it zips 2 lists together, much like the zipper on a real world zip interleaves the teeth of the zip together :) I've just used a hash there as that was the shortest way I could think of interleaving two lists, even though it might not be the best way (doesn't check for the length of the lists for starters).
      HTH

      _________
      broquaint