You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何以惯用方式过滤嵌套可迭代类型的唯一性?

问题:过滤嵌套向量中含重复元素的子向量

假设有一个嵌套向量vec_of_vecs = vec![vec![1,2],vec![1,3],vec![2,2],vec![2,3]],需要用Rust惯用方式过滤掉其中的vec![2,2](保留子向量内元素无重复的项)。

尝试代码

use std::collections::HashSet;
use std::hash::Hash;

fn filter_out_duplicates(vec_of_vecs: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
  vec_of_vecs
     .into_iter()
     .filter(all_unique)
     .collect()
}

pub fn all_unique<T>(iterable: T) -> bool
where
   T: IntoIterator,
   T::Item: Eq + Hash,
{
   let mut unique = HashSet::new();
   iterable.into_iter().all(|x| unique.insert(x))
}

编译错误信息

the method `collect` exists for struct `std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;}`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`<fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;} as std::ops::FnOnce<(&std::vec::Vec<u8>,)>>::Output = bool`
which is required by `std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;}: std::iter::Iterator`
`fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;}: std::ops::FnMut<(&std::vec::Vec<u8>,)>`
which is required by `std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;}: std::iter::Iterator`
`std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;}: std::iter::Iterator`
which is required by `&mut std::iter::Filter<std::vec::IntoIter<std::vec::Vec<u8>>, fn(&std::vec::Vec<u8>) -> bool {all_unique::&lt;&std::vec::Vec<u8>&gt;}: std::iter::Iterator`rustcE0599
filter.rs(15, 1): doesn't satisfy `_: std::iter::Iterator`

错误原因分析

核心问题有两点:

  1. filter方法传递给谓词的是子向量的引用(&Vec<u8>),直接将泛型函数all_unique作为函数指针传入时,编译器无法推导HashSet的具体类型(泛型函数转函数指针要求所有类型参数完全明确)。
  2. 虽然all_unique的实现本身支持处理&Vec<u8>(可转为迭代&u8的迭代器),但函数指针的类型推导环节卡住了。

惯用修复方案

方案一:用闭包包装调用(最简修复)

通过闭包包装all_unique的调用,帮助编译器推导类型,无需修改all_unique的实现:

use std::collections::HashSet;
use std::hash::Hash;

fn filter_out_duplicates(vec_of_vecs: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
    vec_of_vecs
        .into_iter()
        .filter(|v| all_unique(v)) // 闭包辅助类型推导
        .collect()
}

pub fn all_unique<T>(iterable: T) -> bool
where
    T: IntoIterator,
    T::Item: Eq + Hash,
{
    let mut unique = HashSet::new();
    iterable.into_iter().all(|x| unique.insert(x))
}

方案二:明确传递迭代器(更清晰)

调整all_unique接收迭代器类型,然后在filter中明确传递子向量的迭代器,避免类型推导歧义:

use std::collections::HashSet;
use std::hash::Hash;

fn filter_out_duplicates(vec_of_vecs: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
    vec_of_vecs
        .into_iter()
        .filter(|v| all_unique(v.iter())) // 明确传递子向量的迭代器
        .collect()
}

pub fn all_unique<I>(iter: I) -> bool
where
    I: Iterator,
    I::Item: Eq + Hash,
{
    let mut unique = HashSet::new();
    iter.all(|x| unique.insert(x))
}

两种方案都不需要克隆子向量,符合Rust零成本抽象的惯用风格,最终都会正确过滤掉vec![2,2],保留其余子向量。

内容的提问来源于stack exchange,提问作者financial_physician

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:45:31