Search code examples
rustiteration

Remove struct from vector while mutably iterating through it


Relevant Code:

for watermelon in self.watermelons.iter_mut() {
    if watermelon.clr == Color::RED {
        self.score += 1;
        self.watermelons.remove(*self.watermelons.index(watermelon));
    }
}
pub struct Watermelon {
    pub pos: (f32, f32),
    pub size: (i32, i32),
    speed: f64,
    pub clr: Color
}

I get this error:

error[E0277]: the type `[Watermelon]` cannot be indexed by `&mut Watermelon`
--> src/game.rs:46:53
|
46 | ...lf.watermelons.index(watermelon));
|                   ----- ^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
|                   |
|                   required by a bound introduced by this call
|
= help: the trait `SliceIndex<[Watermelon]>` is not implemented for `&mut Watermelon`, which is required by `Vec<Watermelon>: Index<_>`
= note: required for `Vec<Watermelon>` to implement `Index<&mut Watermelon>`

For more information about this error, try `rustc --explain E0277`.

Solution

  • You can use the retain_mut method for that:

    self.watermelons.retain_mut(|watermelon| {
        if watermelon.clr == Color::RED {
            self.score += 1;
            false
        } else {
            true
        }
    });
    

    By the way, the code in your question doesn't actually ever mutate the elements of the vector. If that's the case for your real code too, then you could use retain instead of retain_mut.