法线贴图将函数应用于列表元素并生成结果列表的元素。例如,如果列表是(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>
?
我当然可以编写一个例程来遍历列表。但我正在寻找一种更简单的方法,如减少运算符或像聚集/采取。
答案 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:<+>);
}