简单的方法来映射顺序列表元素组

时间:2017-12-27 08:48:54

标签: list mapping perl6 sequential raku

法线贴图将函数应用于列表元素并生成结果列表的元素。例如,如果列表是(1, 2, 3,)并映射了方形函数,则会得到一个新列表(1, 4, 9,)

有没有办法映射列表中的一组连续元素?例如,如果列表是<8 2 7 2 6 9 4 9 6 1>,并且我想计算列表中每2个元素的总和来制作<10 9 9 8 15 13 13 15 7>

我当然可以编写一个例程来遍历列表。但我正在寻找一种更简单的方法,如减少运算符或像聚集/采取。

2 个答案:

答案 0 :(得分:11)

您可以使用.rotor方法将列表划分为重叠的子列表:

say <8 2 7 2 6 9 4 9 6 1>.rotor(2 => -1);

# Output:
# ((8 2) (2 7) (7 2) (2 6) (6 9) (9 4) (4 9) (9 6) (6 1))

2 => -1是一个Pair参数,它表示该方法应该通过在每一步中“前进两个,后退一个”来生成子列表。

然后,您只需使用.map将您的操作(例如总和)应用于每个子列表:

say <8 2 7 2 6 9 4 9 6 1>.rotor(2 => -1).map(*.sum);

# Output:
# (10 9 9 8 15 13 13 15 7)

答案 1 :(得分:6)

执行此操作的函数式编程方法是两次引用列表,通过元素偏移一个版本,并将它们压缩在一起。这为您提供了后续元素的所有元组。

my @l := <a b c d e f>;
say @l Z @l[1..*]; # output: ((a b) (b c) (c d) (d e) (e f))

如果您不想创建临时变量来保存列表,请使用given(如果您需要语句返回值,请使用do given):

given <8 2 7 2 6 9 4 9 6 1> {
  say ($_ Z $_[1..*]).map: -> [$a, $b] { $a+$b };
}

如果您正在使用带有两个参数的函数,您可能希望在压缩后展平列表,并让map一次取两个元素:

given <8 2 7 2 6 9 4 9 6 1> {
  say ($_ Z $_[1..*]).flat.map(&infix:<+>);
}