我已经解析了一个文件,按行拆分字符串,并希望在每个向量中只留下唯一的元素。我希望vec.dedup()
能够像这样工作:
let mut vec = vec!["a", "b", "a"];
vec.dedup();
assert_eq!(vec, ["a", "b"]);
但它失败了:
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `["a", "b", "a"]`,
right: `["a", "b"]`', src/main.rs:4:4
如何删除重复项?
答案 0 :(得分:10)
如上所述,Vec#dedup
仅从向量中删除连续元素(它比完整重复数据删除便宜得多)。例如,如果向量为vec!["a", "a", "b"]
,它将正常工作。
当然,有多种潜在的解决方案。
为了获得在保留元素原始顺序的同时删除所有重复项的向量,itertools
包提供了unique
适配器。
use itertools::Itertools;
let v = vec!["b", "a", "b"];
let v: Vec<_> = v.into_iter().unique().collect();
assert_eq!(v, ["b", "a"]);
如果元素顺序不重要,您可以先对元素进行排序,然后调用重复数据删除。
let mut v = vec!["a", "b", "a"];
v.sort_unstable();
v.dedup();
assert_eq!(v, ["a", "b"]);
如果快速元素查找很重要,您也可以考虑使用集合类型,例如HashSet
。
let v: HashSet<_> = ["a", "b", "a"].iter().cloned().collect();
let v2: HashSet<_> = ["b", "a"].iter().cloned().collect();
assert_eq!(v, v2);
答案 1 :(得分:2)
另一个答案指出,对于没有重复的集合,HashSet
是更好的选择,我同意这一点。这显示了如何使用Vec
的属性直接对HashMap
进行重复数据删除,而不首先对Vec
进行排序以使用std::vec::Vec::dedup
。
use std::hash::Hash;
use std::collections::HashSet;
fn dedup<T: Eq + Hash + Copy>(v: &mut Vec<T>) { // note the Copy constraint
let mut uniques = HashSet::new();
v.retain(|e| uniques.insert(*e));
}
fn main() {
let mut v = vec!["a", "b", "a"];
dedup(&mut v);
assert_eq!(&v, &vec!["a", "b"]);
}
这是一个快速(O(n))解决方案,但创建HashSet
需要一些额外的内存。