问题
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