Data structures 为什么我在链接迭代器而不是收集到临时哈希集时会得到不一致的结果?

Data structures 为什么我在链接迭代器而不是收集到临时哈希集时会得到不一致的结果?,data-structures,rust,iterator,hashset,Data Structures,Rust,Iterator,Hashset,我正在编写一个Rust函数,它接受一个数字列表和一个最大值,将给定数字的所有倍数相加,直到最大重复数为止,只计算一次。我编写的函数的第一个版本是 use std::collections::HashSet; pub fn sum_of_multiples(limit: u32, factors: &[u32]) -> u32 { let set: HashSet<u32> = factors .iter() .map(|fact

我正在编写一个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)
}
当我取出呼叫中间收集最后一个折叠的时候,我得到了一个不同的答案:

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

我知道迭代器是惰性计算的,但我假设它们是按使用顺序顺序计算的。这是因为hashset的展平行为吗?我不明白为什么第二轮的结果不同,或者2633中的任何一个有什么意义。

您已经删除了中间哈希集,根据您最初的要求声明,它实际上是有用途的:

重复项仅计数一次


删除将值存储在哈希集中的步骤意味着每次重复出现时都会计数,这应该可以解释差异。

您没有删除第二个代码段中的重复项,因为您直接使用了迭代器

我知道像这样合并哈希集可能不是最好的解决方案

由于您需要临时存储来删除重复项,可能您可以使用一个Vec,然后将其放入一个集合中,或者您可以自己对Vec进行排序并过滤重复值,而不是使用集合,但这需要测试

此外,itertools还提供了一个适配器,可在内部跟踪唯一值

这个也应该测试一下。这使您不必担心它是如何实现的

最后,您可以用一个表达式编写函数:

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()
}

函数,该函数获取一个数字列表和一个最大值,并将给定数字的所有倍数相加到最大重复数,只计算一次。对于这类事情,请做一个输入和输出的例子,涵盖你所有的需要,因为我已经迫不及待地想把你所说的与你个人的编码方式相匹配;2只需要一张平面图就可以得到一张平面后的平面图。啊,是的,所以它们连续地结合在一起。我脑子里有它,但我仍然知道它是一套。谢谢此外,itertools还提供了一个适配器,它在内部跟踪唯一的值。@E_net4:也就是说,从复杂性的角度来看,其中有一个HashSet或BTreeSet;itertools只是让写作变得更容易。
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()
}