让我们假设fn scan(int, int) -> int
。
使用时
fn count(x: int, y: int) -> int
{
scan(x - 1, y - 1) + scan(x - 1, y) + scan(x - 1, y + 1) + scan(x, y - 1)
+ scan(x, y + 1) + scan(x + 1, y - 1) + scan(x + 1, y) + scan(x + 1, y + 1)
}
我得到了正确的结果。我试图通过在给定的值范围内对scan
函数进行fold
来获得相同的结果;然而,我似乎做得不对。我目前的尝试是
fn count_fold(x: int, y: int) -> int
{
std::iter::range_inclusive(-1, 1).zip(std::iter::range_inclusive(-1, 1)).fold(0, |a, (i, j)| { a + scan(x + i, y + j) })
}
其似乎仅返回正确结果的子集。我做错了什么?TIA。
当您zip两个迭代器时,您并不是像您想要的那样创建迭代的"乘积"。相反,您是同时迭代两个迭代器,并用迭代的值创建一对。因此,在count_fold
版本中,闭包将只使用以下对调用:
(-1, -1)
(0, 0)
(1, 1)
所以你的count_fold
功能实际上类似于
scan(x - 1, y - 1) + scan(x, y) + scan(x - 1, y + 1)
我可能错了,但我不认为std
中有一个函数可以创建两个迭代器的乘积。
此外,你的count
方法在和中没有使用scan(x, y)
,所以它甚至不是迭代器的乘积;如果您想创建自己的产品迭代器并将其用于此目的,则必须小心这一点。
Cyrille说没有迭代器乘积函数是正确的。然而,可以通过折叠两次来手动获取两个迭代器的乘积:
use std::iter::range_inclusive;
fn count_fold(x: int, y: int) -> int {
range_inclusive(-1, 1).fold(0,
|a, i| range_inclusive(-1, 1).fold(a, |b, j| b + scan(x + i, y + j)))
}
尽管看起来您需要在i == 0 && j == 0
(即)时过滤该情况
fn count_fold(x: int, y: int) -> int {
range_inclusive(-1, 1).fold(0,
|a, i| range_inclusive(-1, 1).fold(a,
|b, j| if i == 0 && j == 0 {b} else {b + scan(x + i, y + j)}))
}
或
fn count_fold(x: int, y: int) -> int {
range_inclusive(-1, 1).fold(0,
|a, i| range_inclusive(-1, 1)
.filter(|&j| !(i == 0 && j == 0))
.fold(a, |b, j| b + scan(x + i, y + j)))
}
然而,我几乎可以肯定地说,这一点更为明确:
fn count_fold(x: int, y: int) -> int {
let mut a = 0;
for i in range_inclusive(-1, 1) {
for j in range_inclusive(-1, 1) {
if !(i == 0 && j == 0) { a += scan(x + i, y + j) }
}
}
a
}