在 Perl 5 中是否有一个优雅的 zip 来交错两个列表? [英] Is there an elegant zip to interleave two lists in Perl 5?

查看:17
本文介绍了在 Perl 5 中是否有一个优雅的 zip 来交错两个列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在 Perl 5 中需要"一个 zip 函数(当时我正在考虑 我如何计算相对时间?),即一个函数,它接受两个列表并将它们压缩"到一个列表中,交错元素.

I recently "needed" a zip function in Perl 5 (while I was thinking about How do I calculate relative time?), i.e. a function that takes two lists and "zips" them together to one list, interleaving the elements.

(伪)示例:

@a=(1, 2, 3);
@b=('apple', 'orange', 'grape');
zip @a, @b; # (1, 'apple', 2, 'orange', 3, 'grape');

Haskell 在 Prelude 中有 zipPerl 6 内置了一个 zip 运算符,但是如何在 Perl 5 中以优雅的方式做到这一点?

Haskell has zip in the Prelude and Perl 6 has a zip operator built in, but how do you do it in an elegant way in Perl 5?

推荐答案

假设您正好有两个列表并且它们的长度完全相同,这里是 merlyn (Randal Schwartz) 最初提出的解决方案,他称之为 perversely perlish:

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:

sub zip2 {
    my $p = @_ / 2; 
    return @_[ map { $_, $_ + $p } 0 .. $p - 1 ];
}

这里发生的事情是,对于一个 10 元素的列表,首先,我们在中间找到轴心点,在本例中为 5,并将其保存在 $p 中.然后我们制作一个索引列表到那个点,在这个例子中是 0 1 2 3 4.接下来我们使用 map 将每个索引与另一个索引配对,该索引与距轴心点的距离相同第一个索引是从一开始,给我们(在这种情况下)0 5 1 6 2 7 3 8 4 9.然后我们从 @_ 中取出一个切片作为索引列表.这意味着如果 'a', 'b', 'c', 1, 2, 3 被传递给 zip2,它将返回重新排列成 的列表'a', 1, 'b', 2, 'c', 3.

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 $p. Then we make a list of indices up to that point, in this case 0 1 2 3 4. Next we use map 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 @_ using that as the list of indices. This means that if 'a', 'b', 'c', 1, 2, 3 is passed to zip2, it will return that list rearranged into 'a', 1, 'b', 2, 'c', 3.

这可以像这样写在一个单独的表达式中:

This can be written in a single expression along ysth’s lines like so:

sub zip2 { @_[map { $_, $_ + @_/2 } 0..(@_/2 - 1)] }

是否要使用任何一种变体取决于您是否能看到自己记住它们是如何工作的,但对我来说,这是一种思维扩展.

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.

这篇关于在 Perl 5 中是否有一个优雅的 zip 来交错两个列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆