根据索引在循环中删除向量的元素

Remove elements of vector in a loop based on index

假设我有一个向量,值是从 1 到 10。我希望如果你发现 5 和 5 彼此相邻,将它们连同下一个元素一起删除。

输入

[1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10]

预期输出

[1, 2, 3, 4] 

这是我的尝试。我正在寻找要删除的索引,但借用规则让我卡住了。

let mut element = vec![1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10];
for (index, val) in element.iter().enumerate() {
    if *val == 5 {
        if let Some(next_val) = element.get(index + 1) {
            if *next_val == 5 {
                //element.drain(index..);
            }
        }
    }
}

Rust 让您免于迭代器失效(其他语言中常见的错误来源)。当您尝试在并发迭代数据结构的同时修改数据结构时,通常会发生这种错误。调用 element.drain(index..) 后,您无法移动到(现已删除的)下一个元素。所以你需要在那个点之后添加一个break以避免内存不安全。

在这种情况下,只需添加 break; 就足以使代码通过编译。但是,要获得更简洁的线性解决方案,请充分利用标准库提供的迭代器和方法:

if let Some(index) = element.windows(2).position(|pair| pair[0] == pair[1]) {
    element.truncate(index);
}
切片上的

windows(2) 给出长度为 2 的子切片上的迭代器,并且 position 调用 returns 该迭代器的第一个元素的索引,其中的两个元素切片是相等的。 (如果不存在这样的对,position returns None。)

我发现 position 闭包随着(当前不稳定的)array_windows 特征变得更加明显:

if let Some(index) = element.array_windows().position(|[x, y]| x == y) {
    element.truncate(index);
}

Playground

相关

你不能做你想做的事,因为你想在迭代向量时从向量中删除一些元素。这是一个很大的错误。请注意,从 vector 中删除任何元素都会使迭代器无效,因此您将访问意想不到的位置,因此 rust 不允许 UBs 你可以使用类似下面的东西

    let mut elements = vec![1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10];
    let mut first_repeated_five_index_op = None;
    for index in 0..elements.len()-1{
        if elements[index] == 5 && elements[index + 1] == 5{
            first_repeated_five_index_op = Some(index);
            break;
        }
    }
    if let Some(first_repeated_five_index) = first_repeated_five_index_op{ 
          elements.truncate(first_repeated_five_index);
    }
    println!("{:?}", elements);

看到一个Demo