正在运行示例:http://is.gd/NBpvmH
fn main() {
show({
let number = b"123456";
for sequence in number.windows(6) {
let product = sequence.iter().fold(1, |a, &b| a * (b as u64));
println!("product of {:?} is {}", sequence, product);
}
});
}
而不是像[49,50,51,52,53,54]的产品那样的输出是15312500000“我需要括号中的正常数字和产品的标准化结果。
尝试使用- b'0'
减去48以获得第5行中的正常数字不起作用,即
a * ((b as u64) -b'0')
或
(a - b'0') * (b as u64)
似乎我在这里遗漏了一些东西,例如我不知道fold()中的'a'和'b'值究竟是什么。任何人都可以开导我吗? :)
答案 0 :(得分:3)
查看the signature of fold
,我们可以看到它需要两个参数:
fn fold<B, F>(self, init: B, f: F) -> B
where F: FnMut(B, Self::Item) -> B
init
,它是一些任意类型B
和f
,它是一个闭包,它从迭代器中获取B
值和一个元素,按顺序计算新的B
值。整个函数返回B
。这些类型强烈暗示会发生什么:在迭代器的连续元素上重复调用闭包f
,将计算的B
值传递给下一个f
调用。检查the implementation证实了这种怀疑:
let mut accum = init;
for x in self {
accum = f(accum, x);
}
accum
它遍历迭代器,将累积状态传递给闭包,以便计算下一个状态。
首先,让我们把类型放在fold
电话上:
let product = sequence.iter().fold(1, |a: u64, &b: &u8| a * (b as u64));
也就是说,我们想要的B
类型是u64
(这是我们最终产品的类型),迭代器的项类型是&u8
,引用一个字节。
现在,我们可以手动内联fold
的定义来计算product
,以尝试澄清所需的行为(我现在忽略了规范化):
let mut accum = 1;
for x in sequence.iter() {
accum = { // the closure
let a: u64 = accum;
let &b: &u8 = x;
a * b as u64
}
}
let product = accum;
简化:
let mut product = 1;
for &b in sequence.iter() {
product = product * (b as u64)
}
希望这更清楚地说明需要发生的事情:b
遍历每个字节,因此需要调整的值是将ASCII编码值降低到预期的0..10范围。 / p>
所以,你是对的:
a * ((b as u64) -b'0')
但是,细节意味着无法编译,类型错误:b'0'
类型为u8
,b as u64
类型为u64
,而且&#39;将-
与u64
和u8
一起使用是不合法的。将标准化移至u64
演员阵容之前将确保此操作正常,因为您将减去b
(u8
}和u8
:
product * (b - b'0') as u64
总而言之,fold
可能看起来更清晰(实际上是工作):
let product = sequence.iter()
.fold(1, |prod, &byte| prod * (byte - b'0') as u64);
(我为在IRC上给你这么令人困惑的代码而道歉。)
答案 1 :(得分:0)
作为fold
的替代方案,您可以使用map
和MultiplicativeIterator::product
。我发现这两个步骤有助于更清楚地了解正在发生的事情。
#![feature(core)]
use std::iter::MultiplicativeIterator;
fn main() {
let number = b"123456";
for sequence in number.windows(6) {
let product = sequence.iter().map(|v| (v - b'0') as u64).product();
println!("product of {:?} is {}", sequence, product);
}
}
您甚至可以选择将调整大小从u8
拆分为u64
:
sequence.iter().map(|v| v - b'0').map(|v| v as u64).product();