<p>I recently "needed" a zip function in Perl 5 (while I was thinking about <a href="https://stackoverflow.com/questions/11/how-do-i-calculate-relative-time">How do I calculate relative time?</a>), i.e. a function that takes two lists and "zips" them together to one list, interleaving the elements.</p>

<p>(Pseudo)example: </p>

<pre><code>@a=(1, 2, 3);
@b=('apple', 'orange', 'grape');
zip @a, @b; # (1, 'apple', 2, 'orange', 3, 'grape');
</code></pre>

<p><a href="http://www.haskell.org/onlinereport/standard-prelude.html" rel="nofollow noreferrer">Haskell has zip in the Prelude</a> and <a href="http://ferreira.nfshost.com/perl6/zip.html" rel="nofollow noreferrer">Perl 6 has a zip operator</a> built in, but how do you do it in an elegant way in Perl 5?</p>

[{'answer_id': 38365, 'author': 'Jason Navarrete', 'author_id': 3920, 'author_profile': 'https://Stackoverflow.com/users/3920', 'pm_score': 5, 'selected': False, 'text': '<p>The <a href="http://search.cpan.org/perldoc?List::MoreUtils" rel="noreferrer">List::MoreUtils</a> module has a zip/mesh function that should do the trick:</p>\n\n<pre><code>use List::MoreUtils qw(zip);\n\nmy @numbers = (1, 2, 3);\nmy @fruit = (\'apple\', \'orange\', \'grape\');\n\nmy @zipped = zip @numbers, @fruit;\n</code></pre>\n\n<p>Here is the source of the mesh function:</p>\n\n<pre><code>sub mesh (\\@\\@;\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@\\@) {\n    my $max = -1;\n    $max &lt; $#$_  &amp;&amp;  ($max = $#$_)  for @_;\n\n    map { my $ix = $_; map $_-&gt;[$ix], @_; } 0..$max; \n}\n</code></pre>\n'}, {'answer_id': 70604, 'author': 'jonfm', 'author_id': 6924, 'author_profile': 'https://Stackoverflow.com/users/6924', 'pm_score': 2, 'selected': False, 'text': "<pre>\nmy @l1 = qw/1 2 3/;\nmy @l2 = qw/7 8 9/;\nmy @out; \npush @out, shift @l1, shift @l2 while ( @l1 || @l2 );\n</pre>\n\n<p>If the lists are a different length, this will put 'undef' in the extra slots but you can easily remedy this if you don't wish to do this. Something like ( @l1[0] &amp;&amp; shift @l1 ) would do it.</p>\n\n<p>Hope this helps!</p>\n"}, {'answer_id': 71895, 'author': 'Aristotle Pagaltzis', 'author_id': 9410, 'author_profile': 'https://Stackoverflow.com/users/9410', 'pm_score': 6, 'selected': True, 'text': "<p>Assuming you have exactly two lists and they are exactly the same length, here is a solution originally by merlyn (Randal Schwartz), who called it perversely perlish:</p>\n\n<pre><code>sub zip2 {\n    my $p = @_ / 2; \n    return @_[ map { $_, $_ + $p } 0 .. $p - 1 ];\n}\n</code></pre>\n\n<p>What happens here is that for a 10-element list, first, we find the pivot point in the middle, in this case 5, and save it in <code>$p</code>. Then we make a list of indices up to that point, in this case 0 1 2 3 4. Next we use <code>map</code> to pair each index with another index that’s at the same distance from the pivot point as the first index is from the start, giving us (in this case) 0 5 1 6 2 7 3 8 4 9. Then we take a slice from <code>@_</code> using that as the list of indices. This means that if <code>'a', 'b', 'c', 1, 2, 3</code> is passed to <code>zip2</code>, it will return that list rearranged into <code>'a', 1, 'b', 2, 'c', 3</code>.</p>\n\n<p>This can be written in a single expression along ysth’s lines like so:</p>\n\n<pre><code>sub zip2 { @_[map { $_, $_ + @_/2 } 0..(@_/2 - 1)] }\n</code></pre>\n\n<p>Whether you’d want to use either variation depends on whether you can see yourself remembering how they work, but for me, it was a mind expander.</p>\n"}, {'answer_id': 100082, 'author': 'ysth', 'author_id': 17389, 'author_profile': 'https://Stackoverflow.com/users/17389', 'pm_score': 2, 'selected': False, 'text': '<p><a href="http://search.cpan.org/perldoc?Algorithm::Loops" rel="nofollow noreferrer"><code>Algorithm::Loops</code></a> is really nice if you do much of this kind of thing.</p>\n\n<p>My own code:</p>\n\n<pre><code>sub zip { @_[map $_&amp;1 ? $_&gt;&gt;1 : ($_&gt;&gt;1)+($#_&gt;&gt;1), 1..@_] }\n</code></pre>\n'}, {'answer_id': 171391, 'author': 'ephemient', 'author_id': 20713, 'author_profile': 'https://Stackoverflow.com/users/20713', 'pm_score': 1, 'selected': False, 'text': '<p>This is totally not an elegant solution, nor is it the best solution by any stretch of the imagination.  But it\'s fun!</p>\n\n<pre><code>package zip;\n\nsub TIEARRAY {\n    my ($class, @self) = @_;\n    bless \\@self, $class;\n}\n\nsub FETCH {\n    my ($self, $index) = @_;\n    $self-&gt;[$index % @$self][$index / @$self];\n}\n\nsub STORE {\n    my ($self, $index, $value) = @_;\n    $self-&gt;[$index % @$self][$index / @$self] = $value;\n}\n\nsub FETCHSIZE {\n    my ($self) = @_;\n    my $size = 0;\n    @$_ &gt; $size and $size = @$_ for @$self;\n    $size * @$self;\n}\n\nsub CLEAR {\n    my ($self) = @_;\n    @$_ = () for @$self;\n}\n\npackage main;\n\nmy @a = qw(a b c d e f g);\nmy @b = 1 .. 7;\n\ntie my @c, zip =&gt; \\@a, \\@b;\n\nprint "@c\\n";  # ==&gt; a 1 b 2 c 3 d 4 e 5 f 6 g 7\n</code></pre>\n\n<p>How to handle <code>STORESIZE</code>/<code>PUSH</code>/<code>POP</code>/<code>SHIFT</code>/<code>UNSHIFT</code>/<code>SPLICE</code> is an exercise left to the reader.</p>\n'}, {'answer_id': 486162, 'author': 'jmcnamara', 'author_id': 10238, 'author_profile': 'https://Stackoverflow.com/users/10238', 'pm_score': 3, 'selected': False, 'text': '<p>For arrays of the same length:</p>\n\n<pre><code>my @zipped = ( @a, @b )[ map { $_, $_ + @a } ( 0 .. $#a ) ];\n</code></pre>\n'}, {'answer_id': 544390, 'author': 'Frank', 'author_id': 60628, 'author_profile': 'https://Stackoverflow.com/users/60628', 'pm_score': 4, 'selected': False, 'text': "<p>I find the following solution straightforward and easy to read:</p>\n\n<pre><code>@a = (1, 2, 3);\n@b = ('apple', 'orange', 'grape');\n@zipped = map {($a[$_], $b[$_])} (0 .. $#a);\n</code></pre>\n\n<p>I believe it's also faster than solutions that create the array in a wrong order first and then use slice to reorder, or solutions that modify <code>@a</code> and <code>@b</code>.</p>\n"}]
['https://Stackoverflow.com/questions/38345', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2905/']