2017-12-04 1 views
-2

파일을 구문 분석 한 다음 줄별로 줄을 나누고 각 벡터에 고유 한 요소 만 남기고 싶습니다.문자열 벡터를 중복 제거하는 방법은 무엇입니까?

let mut vec = vec!["a", "b", "a"]; 
vec.dedup(); 
assert_eq!(vec, ["a", "b"]); 

하지만 실패 :이 같은 일을 vec.dedup() 기대

thread 'main' panicked at 'assertion failed: `(left == right)` 
    left: `["a", "b", "a"]`, 
right: `["a", "b"]`', src/main.rs:4:4 

어떻게 중복을 제거 할 수 있습니까?

+2

문서에서 dedup은 연속 된 중복 만 제거한다고 설명합니다. 아마 먼저 정렬할까요? https://doc.rust-lang.org/std/vec/struct.Vec.html – lwi

답변

5

문서에서 알 수 있듯이 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); 
2

다른 대답은 HashSet 내가 동의 중복없이 수집을위한 더 나은 선택이라고 지적했다. 이 방법은 이라는 속성을 사용하고 Vec을 먼저 정렬하여 std::vec::Vec::dedup으로 정렬하지 않고 Vec을 직접 중복 제거하는 방법을 보여줍니다.

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 만들기 일부 여분의 메모리를 필요로한다.

+0

어떤 식 으로든 이것은 '고유'어댑터의 인라인 형식이어야합니다. –

관련 문제