借用检查器让我很难找到优雅的实现方式。这是一个最小的例子:
use std::collections::VecDeque;
fn main() {
let mut vec1 = VecDeque::new();
vec1.push_back(2.);
let mut vec2 = VecDeque::new();
vec2.push_back(1.);
while let (Some(x), Some(y)) = (vec1.front_mut(), vec2.front_mut()) {
if x < y {
*y -= *x;
vec1.pop_front();
} else {
*x -= *y;
vec2.pop_front();
}
}
assert_eq!(vec2.len(), 0);
assert_eq!(vec1.pop_front(), Some(1.));
}
这不会编译:
error[E0499]: cannot borrow `vec1` as mutable more than once at a time
--> src/main.rs:13:13
|
10 | while let (Some(x), Some(y)) = (vec1.front_mut(), vec2.front_mut()) {
| ---- first mutable borrow occurs here
...
13 | vec1.pop_front();
| ^^^^ second mutable borrow occurs here
...
18 | }
| - first borrow ends here
error[E0499]: cannot borrow `vec2` as mutable more than once at a time
--> src/main.rs:16:13
|
10 | while let (Some(x), Some(y)) = (vec1.front_mut(), vec2.front_mut()) {
| ---- first mutable borrow occurs here
...
16 | vec2.pop_front();
| ^^^^ second mutable borrow occurs here
17 | }
18 | }
| - first borrow ends here
if x < y
范围必然嵌套在x
和y
的范围内,那么我怎样才能以{1}} / vec1
为条件进行变更元件?
答案 0 :(得分:3)
你可以这样做:
use std::collections::VecDeque;
fn main() {
let mut vec1 = VecDeque::new();
vec1.push_back(2.);
let mut vec2 = VecDeque::new();
vec2.push_back(1.);
loop {
let pop_vec1;
if let (Some(x), Some(y)) = (vec1.front_mut(), vec2.front_mut()) {
if x < y {
*y -= *x;
pop_vec1 = true;
} else {
*x -= *y;
pop_vec1 = false;
}
} else {
break;
}
if pop_vec1 {
vec1.pop_front();
} else {
vec2.pop_front();
}
}
assert_eq!(vec2.len(), 0);
assert_eq!(vec1.pop_front(), Some(1.));
}
或者如果您更喜欢使用较少行的循环:
loop {
let pop_vec1 = match (vec1.front_mut(), vec2.front_mut()) {
(Some(ref x), Some(ref mut y)) if x < y => { **y -= **x; true },
(Some(x), Some(y)) => { *x -= *y; false },
_ => break,
};
VecDeque::pop_front(if pop_vec1 { &mut vec1 } else { &mut vec2 });
}
不是很优雅,但它有效。
VecDeque
缺少方法like Vec::drain_filter
。也许Rust团队会添加它。