根据某些条件从Vec中删除元素

时间:2016-06-13 14:33:03

标签: rust

我的代码如下所示:

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但我不允许有两个可变借用或一个可变借用,如果存在一个完全有意义的不可变借用。

我想最简单的事情就是clonefiltercollect,但我不能克隆或复制。

我该怎么做?

2 个答案:

答案 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
});