作者:ltxys | 来源:互联网 | 2022-12-04 15:12
我正在写一个Rust函数,它接受一个数字列表和一个最大值,并将给定数字的所有倍数加到最大值(重复数只计算一次).我写的函数的第一个版本是
use std::collections::HashSet;
pub fn sum_of_multiples(limit: u32, factors: &[u32]) -> u32 {
let set: HashSet = factors
.iter()
.map(|factor| {
let top: u32 = (limit - 1) / factor;
(1..=top).map(move |num| num * factor)
}).flatten()
.collect();
set.iter().fold(0, |acc, num| acc + num)
}
(我知道合并HashSets
这样可能不是最好的解决方案).这给出了预期的结果:
println!("{}", sum_of_multiples(100, &[3, 5])) // 2318
当我把呼叫collect
从中间取出并连接到最后一个时fold
,我得到了一个不同的答案:
pub fn sum_of_multiples(limit: u32, factors: &[u32]) -> u32 {
let val: u32 = factors
.iter()
.map(|factor| {
let top: u32 = (limit - 1) / factor;
(1..=top).map(move |num| num * factor)
}).flatten()
.fold(0, |acc, num| acc + num);
val
}
结果:
println!("{}", sum_of_multiples(100, &[3, 5])) // 2633
我知道迭代器是懒惰地评估的,但我假设它们按照它们被使用的顺序按顺序进行评估.这是因为行为flatten
与HashSet
S' 我不明白为什么第二轮结果不同,或2633的重要性(如果有的话)是什么.
1> Stargateur..:
您没有删除第二个代码段中的重复项,因为您直接使用了迭代器.
(我知道这样的合并HashSet
可能不是最好的解决方案).
由于您需要临时存储来删除重复项,也许您可以使用a Vec
然后将其放入集合中,或者不使用集合,您可以Vec
自己对重复值进行排序和过滤,但这需要测试.
此外,itertools
还提供了一个独特的适配器,可在内部跟踪唯一值.- E_net4
这个也应该进行测试.这使您不必担心它是如何实现的.
最后,您可以在一个表达式中编写函数:
use std::collections::HashSet;
pub fn sum_of_multiples(limit: u32, factors: &[u32]) -> u32 {
factors
.iter()
.flat_map(|factor| {
let top = (limit - 1) / factor;
(1..=top).map(move |num| num * factor)
})
.collect::>()
.iter()
.sum()
}
此外,`itertools`提供了一个[`unique`](https://docs.rs/itertools/0.7.8/itertools/trait.Itertools.html#method.unique)适配器,它在内部跟踪唯一值.