Rust 如何检查切片中是否存在重复项?

Rust 如何检查切片中是否存在重复项?,rust,Rust,是否有一种本机方法来检查切片是否有重复项?现在,我用这个: 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_

是否有一种本机方法来检查切片是否有重复项?现在,我用这个:

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);
}
fn具有_dup(切片:&[T])->bool{
对于1..slice.len()中的i{
如果片[i..]包含(&片[i-1]){
返回true;
}
}
假的
}
fn main(){
assert_eq!(has_dup(&[1,2,3,2,5,6]),true);
assert_eq!(has_dup(&[1,2,3,4,5,6]),false);
}
但是对于这种基本操作,我不喜欢使用手工编写的代码


如果在标准库中没有可用的函数来执行此操作,这是优化代码的一种方法吗?我知道索引切片并不是最优化的方式(
for I in slice{}
vs
for I in 0..slice.len(){slice[I]}
)。

索引并不是优化的,只是在迭代器解决方案存在的情况下它不是惯用的方法。没有迭代器解决方案,因此您的代码已经是最佳解决方案

如果你想走一条更实用的道路,你可以写

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

就算法复杂性而言,通常最好跟踪索引中的唯一值。如果可以使用
哈希
Eq
检查相等性,则可以尝试此实用程序函数:

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()));
fn有独特的元素(iter:T)->bool
哪里
T:迭代器,
T::Item:Eq+Hash,
{
让mut uniq=HashSet::new();
iter.into_iter().all(移动| x | uniq.insert(x))
}
断言!(!具有独特的元素(vec![10,20,30,10,50]);
断言!(具有独特的元素(vec![10,20,30,40,50]);
断言!(具有唯一的元素(Vec:::new());


同样,如果您的元素没有实现
Hash
,但是实现了,那么可以使用()来代替。

索引检查索引是否在边界内。所以有一个(小)开销。但是这个小的开销可以在循环中产生更大的差异。LLVM将处理这些简单的循环。不过,你在一般情况下是正确的。这基本上是正确的。有比对照列表的其余部分检查每个元素更有效的方法,即
O(n^2)
,但这些都不是在std中实现的。然而,折衷的办法是它们可能需要更多的内存。请参阅关于rosetta代码的方法。这是删除vs只是检查,但它应该让你知道如何做。@PaoloFalabella这很奇怪,这样一个基本算法不在标准中。@Boiethios为什么你认为这是一个“基本”算法?即使是这样,记住很多人认为“基本”的随机数生成的东西都是由一个板条箱提供的。我喜欢这个解决方案,但是在类型上有更多的限制(<代码>散列< /代码> +代码>克隆< /代码>)不能做鸡蛋而不打破鸡蛋。P为了更快地查找,需要哈希函数或总顺序关系。我不确定是否可以避免复制以前获取的项目。是否可以使用
.clone().all(move | x | uniq.insert(x))
?。不需要
ExactSizeIterator
约束。是的,这是一个很好的改进(您甚至不需要克隆迭代器)。它现在更新了。@Boiethios:Note about
Clone
,如果您在
&Vec
上调用此方法,那么您将得到一个默认可克隆的引用迭代器。我认为用价值来称呼它是非常罕见的。