Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing elements from a Vec based on some condition [duplicate]

Tags:

rust

My code looks like this:

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

Note that Bar is not allowed to be copied or cloned.

I want to delete all Bars that don't satisfy that condition. Initially I thought I could just iterate over them and call remove but I am not allowed to have two mutable borrows or one mutable borrow if there is an immutable borrow which makes total sense.

I guess the easiest thing would be to just clone, filter and collect, but I am not allowed to clone or copy.

How would I do this?

like image 656
Maik Klein Avatar asked Jun 13 '16 14:06

Maik Klein


2 Answers

If you look at the interface of Vec, you will not find a method that erases some elements based on a predicate. Instead you will find retain which keeps the elements based on a predicate.

Of course, both are symmetric, it's just that retain is harder to find if you filter method names by "remove" or "erase" (it does contain "remove" in its description).

The example provided speaks for itself:

let mut vec = vec![1, 2, 3, 4];
vec.retain(|&x| x % 2 == 0);
assert_eq!(vec, [2, 4]);
like image 58
Matthieu M. Avatar answered Oct 26 '22 07:10

Matthieu M.


In nightly Rust, you can use 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);
}

What's extra interesting about drain_filter is that you can get the rejected values as it returns an iterator of them:

let rejects: Vec<_> = bars.drain_filter(|b| b.i < 10).collect();

You can also choose to modify the value being iterated over:

bars.drain_filter(|b| {
    b.i -= 1;
    b.i < 10
});
like image 34
Shepmaster Avatar answered Oct 26 '22 08:10

Shepmaster