我希望迭代一个数组/向量并修改多个元素,因为这是最佳解决方案。我不想一次又一次地扫描它只是因为Rust对借款不满意。
我在排序的向量中存储了一个表示为STDERR
的区间列表,我想添加一个新区间。它可能重叠,所以我想删除所有不再需要的元素。我想一气呵成。算法看起来像这样(我削减了一些部分):
[start;stop]
由于借用规则,它在几个地方都失败了。有没有办法
有onlyExternal
可用,但我不知道如何在此处应用它。
答案 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
时删除 i2
或vec.remove(i3)
之前的任何值,则next
和r
中的引用因为所有的值都会移动,所以会失效。i5
在i1
或i2
之前,则会发生同样的事情,只是在另一个方向。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。