使用rotor操作列表

假设有一个 0..100 的数字区间, 需要分成下面这样的区间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0..5
5..10
10..15
15..20
20..25
25..30
30..35
35..40
40..45
45..50
50..55
55..60
60..65
65..70
70..75
75..80
80..85
85..90
90..95
95..100

rotor 来拯救:

1
.minmax.say for (0..100).rotor(6 => -1)

我想偷懒用程序生成下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if (current >=0 && current < 5) "0"
if (current >=5 && current < 10) "1"
if (current >=10 && current < 15) "2"
if (current >=15 && current < 20) "3"
if (current >=20 && current < 25) "4"
if (current >=25 && current < 30) "5"
if (current >=30 && current < 35) "6"
if (current >=35 && current < 40) "7"
if (current >=40 && current < 45) "8"
if (current >=45 && current < 50) "9"
if (current >=50 && current < 55) "10"
if (current >=55 && current < 60) "11"
if (current >=60 && current < 65) "12"
if (current >=65 && current < 70) "13"
if (current >=70 && current < 75) "14"
if (current >=75 && current < 80) "15"
if (current >=80 && current < 85) "16"
if (current >=85 && current < 90) "17"
if (current >=90 && current < 95) "18"
if (current >=95 && current < 100) "19"
1
2
3
for (0..100).rotor(6 => -1) -> $r { 
say "if (current >={$r.min} && current < {$r.max}) " ~ '"' ~ $++ ~ '"'
}

rotor 是操作列表的利器,

1
(1..7).rotor(3).join('|') # 1 2 3|4 5 6

7 被舍弃了。如果你也需要 7, 那么使用 :partial 副词。

1
(1..7).rotor(3, :partial).join('|') # 1 2 3|4 5 6|7

rotor 的第一个参数是一个数组, 数组的元素有俩种:

  • 一个整数
  • 一个 Pair

实际上:

1
(1..7).rotor(3).join('|') # 1 2 3|4 5 6

相当于

1
(1..7).rotor(3 => 0).join('|') # 1 2 3|4 5 6

Pair 中的 key 指定所返回的子列表的大小, Pair 的 value 指定子列表之间的间隙, 这个间隙可为正, 可为负。如果是正数则跳过, 为负数则重叠一些元素。

以(M => N)这个 Pair 为例, M 是所返回的子列表中的元素个数, N 是缝隙的大小, N < 0 时, 发生重叠, N > 0 时, 发生缝隙。

N > 0 时:

1
(1..7).rotor(2 => 1, :partial).join('|') # 1 2|4 5|7

N < 0 时:

1
(1..7).rotor(2 => -1, :partial).join('|') # 1 2|2 3|3 4|4 5|5 6|6 7|7

来看 rotor 的函数签名:

1
(*@cycle, Bool() :$partial --> Seq:D)

@circle 除了可以包含整数, Pair 等单个元素之外, 还可以同时包含整数和 Pair, rotor 会循环使用这几种元素, 例子:

1
(1..7).rotor(2,3, :partial).join('|') # 1 2|3 4 5|6 7
1
(1..7).rotor(1 => 1,3, :partial).join('|') # 1|3 4 5|6
1
(1..7).rotor(1 => 1,2 => -1, :partial).join('|') # 1|3 4|4|6 7|7