rust 如何返回一个迭代器在迭代器的项目的项目?

xoshrz7s  于 2023-11-19  发布在  其他
关注(0)|答案(2)|浏览(96)

我有一个函数,它的输入是HashSet<char> s上的迭代器,并计算交集。公共的char s作为新创建的HashSet<char>返回,我想将其更改为char s上的通用迭代器。
因此,我有以下代码(rust-playground上的工作示例):

fn intersect<I>(sets: I) -> HashSet<char>
where
    I: IntoIterator + Clone,
    I::Item: Borrow<HashSet<char>> + Clone,
{
    let first = match sets.clone().into_iter().next() {
        Some(val) => val.clone(),
        None => return HashSet::default(),
    };

    first
        .borrow()
        .iter()
        .filter(move |elem| {
            sets.clone()
                .into_iter()
                .all(|set| set.borrow().contains(elem))
        })
        .cloned()
        .collect()
}

字符串
基本上,我想在函数外部调用.collect()。我试过删除这一位,并将返回类型改为:impl Iterator<Item = char>,但这只会导致错误help: the traitIteratoris not implemented forHashSet<_, _>``。

lskq00tm

lskq00tm1#

一个选项是添加一个输出类型参数:

fn intersect<O, I>(sets: I) -> O
where
    I: IntoIterator + Clone,
    I::Item: Borrow<HashSet<char>> + Clone,
    O: FromIterator<char>,
{
    let first = match sets.clone().into_iter().next() {
        Some(val) => val.clone(),
        None => return O::from_iter([]),
    };

    first
        // ...
        .collect()
}

字符串
collect()的调用仍然在函数内部,但调用者可以请求他们需要的集合:

fn main() {
    let data = vec![
        HashSet::from(['a', 'b', 'c']),
        HashSet::from(['a', 'd', 'e']),
        HashSet::from(['a', 'd']),
    ];

    // this could be Vec<char>
    let common: HashSet<char> = intersect(&data);
    println!("{:?}", common);
}


Playground

ivqmmu1c

ivqmmu1c2#

intersect()的实现效率相当低。它为第一个集合的每个元素复制了整个集合的迭代器。你可以通过从第一个集合的副本开始,迭代剩余的集合,只保留也包含在其他集合中的元素来更有效地编写实现:

fn intersect<'a, I, T>(sets: I) -> HashSet<T>
where
    I: IntoIterator<Item = &'a HashSet<T>>,
    T: 'a + Copy + Eq + Hash,
{
    let mut sets = sets.into_iter();
    let mut result: HashSet<T> = sets
        .next()
        .map(|s| s.iter().copied().collect())
        .unwrap_or(HashSet::new());
    for s in sets {
        result.retain(|x| s.contains(x));
    }
    result
}

字符串
这仍然返回一个HashSet。然而,如果你想要一个有效的解决方案来解决你的问题,你无论如何都需要创建一个HashSet。你可以稍后将它转换为你想要的任何东西,例如Vec::from_iter(intersect(...))。我看不出改变函数的返回类型有什么好处。

相关问题