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

Mai*_*ein 5 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));
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,Bar不允许复制或克隆.

我想删除所有Bar不满足该条件的s.最初我以为我可以迭代它们并调用remove但是我不允许有两个可变借用或一个可变借用,如果存在一个完全有意义的不可变借用.

我想最简单的事情是只clone,filtercollect,但我不能克隆或复制.

我该怎么做?

Mat*_* M. 9

如果你查看界面Vec,你将找不到基于谓词擦除某些元素的方法.相反,你会发现retain保持基于谓词的元素.

当然,两者都是对称的,retain如果你通过"删除"或"擦除"过滤方法名称,它就更难找到(它的描述中确实包含"删除").

提供的示例说明了一切:

let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| x % 2 == 0);
assert_eq!(vec, [2, 4]);
Run Code Online (Sandbox Code Playgroud)


She*_*ter 6

在每晚的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);
}
Run Code Online (Sandbox Code Playgroud)

有趣的drain_filter是,您可以获取被拒绝的值,因为它返回了它们的迭代器:

let rejects: Vec<_> = bars.drain_filter(|b| b.i < 10).collect();
Run Code Online (Sandbox Code Playgroud)

您还可以选择修改要迭代的值:

bars.drain_filter(|b| {
    b.i -= 1;
    b.i < 10
});
Run Code Online (Sandbox Code Playgroud)