Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if there are duplicates in a slice?

Tags:

rust

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] }).

like image 290
Boiethios Avatar asked Oct 16 '17 09:10

Boiethios


2 Answers

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).

like image 126
E_net4 stands with Ukraine Avatar answered Nov 09 '22 06:11

E_net4 stands with Ukraine


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]))
like image 27
oli_obk Avatar answered Nov 09 '22 05:11

oli_obk