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] }
).
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).
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]))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With