我的代码如下所示:
struct Bar {
i: i32,
}
struct Foo {
v: Vec<Bar>,
}
impl Foo {
fn foo(&mut self) {
self.v.drain(self.v.iter().filter(|b| b.i < 10));
}
}
请注意,不允许复制或克隆Bar
。
我想删除所有不满足该条件的Bar
。最初我以为我可以迭代它们并调用remove
但我不允许有两个可变借用或一个可变借用,如果存在一个完全有意义的不可变借用。
我想最简单的事情就是clone
,filter
和collect
,但我不能克隆或复制。
我该怎么做?
答案 0 :(得分:9)
如果查看Vec
的界面,您将找不到基于谓词删除某些元素的方法。相反,您会发现retain
基于谓词保留元素。
当然,两者都是对称的,如果你通过&#34;删除&#34;来过滤方法名称,那么retain
就更难找到了。或&#34;擦除&#34; (它确实包含&#34;删除&#34;在其描述中)。
提供的例子说明了一切:
let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| x % 2 == 0);
assert_eq!(vec, [2, 4]);
答案 1 :(得分:5)
在夜间Rust中,您可以使用Vec::drain_filter
:
#![feature(drain_filter)]
#[derive(Debug)]
struct Bar {
i: i32,
}
fn main() {
let mut bars = vec![Bar { i: 1 }, Bar { i: 10 }, Bar { i: 3 }, Bar { i: 100 }];
bars.drain_filter(|b| b.i < 10);
println!("{:?}", bars);
}
drain_filter
更令人感兴趣的是你可以获得被拒绝的值,因为它返回了它们的迭代器:
let rejects: Vec<_> = bars.drain_filter(|b| b.i < 10).collect();
您还可以选择修改正在迭代的值:
bars.drain_filter(|b| {
b.i -= 1;
b.i < 10
});