如何迭代矢量一次并插入/删除/修改多个元素?

时间:2017-08-05 00:41:48

标签: algorithm rust

我希望迭代一个数组/向量并修改多个元素,因为这是最佳解决方案。我不想一次又一次地扫描它只是因为Rust对借款不满意。

我在排序的向量中存储了一个表示为STDERR的区间列表,我想添加一个新区间。它可能重叠,所以我想删除所有不再需要的元素。我想一气呵成。算法看起来像这样(我削减了一些部分):

[start;stop]

由于借用规则,它在几个地方都失败了。有没有办法

  1. 一次性使用迭代器
  2. 解决借贷问题
  3. onlyExternal可用,但我不知道如何在此处应用它。

1 个答案:

答案 0 :(得分:5)

一般情况下,您无法,因为这正是Rust阻止的一类错误。检查我用唯一变量替换i的事件序列,因为编译器无法知道将使用哪些值。

let r = &mut vec[i1];
let next = &vec[i2];
vec.remove(i3);
vec[i4] = bigger.union(next);         
vec.insert(i5, addition);
  • 如果您在调用i1时删除 i2vec.remove(i3)之前的任何值,则nextr中的引用因为所有的值都会移动,所以会失效。
  • 如果i5i1i2之前,则会发生同样的事情,只是在另一个方向。
  • 如果i4等于i2,则next不可变值将会更改。
  • 如果i4等于i1,则对r的修改将通过另一条路径发生,而不是可变引用的单一所有者。

注意每个对应于编译器告诉你的要点。

可能这些案例的某些可能会通过非词汇生命周期修复,如果编译器变得足够聪明,无法理解您不再需要有参考。通过数组索引更改向量的情况无济于事;编译器不够智能,无法跟踪您的数学并证明您从未触及过错误的"如果索引是。

,也不会足够聪明地认识到数组中的两个引用是不相交的

此特定情况中,由于您的类型实现了Copy,因此请使用它来获取值。需要时直接写回矢量。如果您从不借用,则无法借用

fn main() {
    let mut vec = vec![
        Interval::new(1, 1),
        Interval::new(2, 3),
        Interval::new(6, 7),
    ];
    let addition = Interval::new(2, 5);
    let (mut i, len) = (0, vec.len());
    while i < len {
        let r = vec[i];
        if r == addition {
            return;
        }
        if addition.adjacent(&r) || !addition.disjoint(&r) {
            let mut bigger = addition.union(&r);
            vec[i] = bigger;
            while i < len - 1 {
                i += 1;
                let next = vec[i + 1];
                if !bigger.adjacent(&next) && bigger.disjoint(&next) {
                    break;
                }
                vec.remove(i); 
                i -= 1;
                vec[i] = bigger.union(&next);
            }
            return;
        }
        if addition.starts_before_disjoint(&r) {
            vec.insert(i - 1, addition);
        }
        i += 1;
    }
}

实际上,我做loganfsmyth suggests并更改算法以获取一段时间间隔并返回新的Vec。如果你这么做很多,你可以在两个预先分配的Vec之间来回翻转,但在那时,可能是一个比矢量好得多的数据结构;也许是interval tree