How to check if there are duplicates in a slice?

*爱你&永不变心* 提交于 2020-07-08 06:25:08

问题


Is there a native way to check if a slice has duplicates? For now, I use this:

fn has_dup<T: PartialEq>(slice: &[T]) -> bool {
    for i in 1..slice.len() {
        if slice[i..].contains(&slice[i - 1]) {
            return true;
        }
    }
    false
}

fn main() {
    assert_eq!(has_dup(&[1, 2, 3, 2, 5, 6]), true);
    assert_eq!(has_dup(&[1, 2, 3, 4, 5, 6]), false);
}

but for this kind of basic operations, I do not like to use hand-made code.

If there is no available function to do this in the standard library, is it a way to optimize my code? I know that indexing the slice is not the most optimized way (for i in slice {} vs for i in 0..slice.len() { slice[i] }).


回答1:


In terms of algorithmic complexity, it is often better to keep track of unique values in an index. If you can check equality with Hash and Eq, you can try this utility function:

fn has_unique_elements<T>(iter: T) -> bool
where
    T: IntoIterator,
    T::Item: Eq + Hash,
{
    let mut uniq = HashSet::new();
    iter.into_iter().all(move |x| uniq.insert(x))
}

assert!(!has_unique_elements(vec![10, 20, 30, 10, 50]));
assert!(has_unique_elements(vec![10, 20, 30, 40, 50]));
assert!(has_unique_elements(Vec::<u8>::new()));

Playground

Likewise, if your elements don't implement Hash but do implement Ord, you can use a BTreeSet instead (Playground).




回答2:


Indexing is not less optimized, it's just not idiomatic in the presence of an iterator solution. There is no iterator solution, so your code is already the optimal solution.

If you want to go down a more functional road, you can write

(1..slice.len()).any(|i| slice[i..].contains(&slice[i - 1]))


来源:https://stackoverflow.com/questions/46766560/how-to-check-if-there-are-duplicates-in-a-slice

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!