【问题标题】:Vec::dedup does not work — how do I deduplicate a vector of strings?Vec::dedup 不起作用 — 如何对字符串向量进行重复数据删除?
【发布时间】:2018-05-18 02:39:20
【问题描述】:

我已经解析了一个文件,将字符串逐行拆分,并希望在每个向量中只保留唯一元素。我希望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

如何删除重复项?

【问题讨论】:

标签: string vector rust


【解决方案1】:

另一个答案指出HashSet 是没有重复的集合的更好选择,我同意这一点。这显示了如何使用HashMap 的属性直接对Vec 进行重复数据删除,而不首先对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 需要一些额外的内存。

【讨论】:

  • 在某种程度上,这应该是 unique 适配器的内联形式。
【解决方案2】:

如文档所述,Vec#dedup 仅从向量中删除 连续 元素(它比完全重复数据删除便宜得多)。例如,如果向量是vec!["a", "a", "b"],它就可以正常工作。

当然,有多种可能的解决方案。

为了在保留元素的原始顺序的同时获得一个删除了所有重复项的向量,itertools crate 提供了一个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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2014-04-29
    • 2021-03-15
    相关资源
    最近更新 更多