avy*_*avy 0 iterator hashset rust data-structures
我正在写一个Rust函数,它接受一个数字列表和一个最大值,并将给定数字的所有倍数加到最大值(重复数只计算一次).我写的函数的第一个版本是
use std::collections::HashSet;
pub fn sum_of_multiples(limit: u32, factors: &[u32]) -> u32 {
let set: HashSet<u32> = 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)
}
Run Code Online (Sandbox Code Playgroud)
(我知道合并HashSets
这样可能不是最好的解决方案).这给出了预期的结果:
println!("{}", sum_of_multiples(100, &[3, 5])) // 2318
Run Code Online (Sandbox Code Playgroud)
当我把呼叫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
}
Run Code Online (Sandbox Code Playgroud)
结果:
println!("{}", sum_of_multiples(100, &[3, 5])) // 2633
Run Code Online (Sandbox Code Playgroud)
我知道迭代器是懒惰地评估的,但我假设它们按照它们被使用的顺序按顺序进行评估.这是因为行为flatten
与HashSet
S' 我不明白为什么第二轮结果不同,或2633的重要性(如果有的话)是什么.
您没有删除第二个代码段中的重复项,因为您直接使用了迭代器.
(我知道这样的合并
HashSet
可能不是最好的解决方案).
由于您需要临时存储来删除重复项,也许您可以使用a Vec
然后将其放入集合中,或者不使用集合,您可以Vec
自己对重复值进行排序和过滤,但这需要测试.
这个也应该进行测试.这使您不必担心它是如何实现的.
最后,您可以在一个表达式中编写函数:
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::<HashSet<u32>>()
.iter()
.sum()
}
Run Code Online (Sandbox Code Playgroud)