如何用Rust实现类似C++ std::copy_if的泛型集合克隆筛选函数
实现Rust中类似C++ std::copy_if的泛型集合筛选克隆函数
原代码的问题
- 先克隆整个集合再删除元素的方式效率低下,且不适用于所有集合类型(比如部分集合没有便捷的单元素删除方法)
- 泛型约束冗余且限制过多:同时要求
Clone + Copy没必要,IntoIterator<Item = &'a ItemType>只能处理引用迭代,无法直接接收值类型集合 - 遍历逻辑错误:
res.into_iter()会转移res的所有权,遍历过程中无法修改原集合,导致res.remove()无法调用
正确的通用实现
我们可以利用Rust的迭代器特性和FromIterator trait,实现一个适配所有集合类型的clone_if函数,只克隆符合条件的元素并收集到目标集合中:
use std::borrow::Borrow; fn clone_if<Input, ItemType, Pred, Output>(input: Input, pred: Pred) -> Output where Input: IntoIterator, Input::Item: Borrow<ItemType>, ItemType: Clone, Pred: Fn(&ItemType) -> bool, Output: FromIterator<ItemType>, { input.into_iter() .filter(|item| pred(item.borrow())) .map(|item| item.borrow().clone()) .collect() } fn main() { let first_list = vec![1, 2, 3, 4, 5, 6]; // 输入值类型集合,返回Vec<i32> let even_values = clone_if(first_list.clone(), |&item| item % 2 == 0); assert_eq!(vec![2, 4, 6], even_values); // 输入引用类型集合,返回Vec<i32> let even_refs = clone_if(&first_list, |item| item % 2 == 0); assert_eq!(vec![2, 4, 6], even_refs); // 也可以适配其他集合类型,比如HashSet use std::collections::HashSet; let set: HashSet<i32> = [1,2,3,4,5,6].into(); let even_set: HashSet<i32> = clone_if(&set, |&item| item % 2 == 0); assert!(even_set.contains(&2) && even_set.contains(&4) && even_set.contains(&6)); }
实现说明
- 泛型约束设计:
Input: IntoIterator:允许函数接收任何可转换为迭代器的类型(值或引用)Input::Item: Borrow<ItemType>:统一处理值和引用类型的迭代元素,确保能获取到ItemType的引用ItemType: Clone:保证元素可以被克隆Output: FromIterator<ItemType>:允许将筛选后的克隆元素收集到任意实现了该trait的集合类型中(Vec、HashSet等)
- 迭代器流程:
- 将输入转换为迭代器
- 使用
filter保留符合条件的元素 - 克隆筛选后的元素
- 用
collect将元素收集到目标集合类型中
针对Vec的简化实现
如果只需要针对Vec优化,可以简化约束,直接利用Vec的迭代器特性:
fn vec_clone_if<T, Pred>(vec: Vec<T>, pred: Pred) -> Vec<T> where T: Clone, Pred: Fn(&T) -> bool, { vec.into_iter() .filter(pred) .cloned() .collect() }
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

