I'm trying to remove some elements from a vector, based on a predicate, and collecting the result. Here's a (not working) example with an expected result:
let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6]; let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect(); assert_eq!(v, vec![1, 3, 5]); assert_eq!(drained, vec![2, 4, 6]);
This results in the error
error[E0599]: no method named `drain` found for type `std::iter::Filter<std::slice::Iter<'_, i32>, [closure@src/main.rs:4:45: 4:62]>` in the current scope --> src/main.rs:4:64 | 4 | let drained: Vec<i32> = v.iter().filter(|e| (*e) % 2 == 0).drain(..).collect(); | ^^^^^
There are several alternatives I looked at, none of them seem to be doing what I want:
Vec::retain
removes the elements from the vector, but doesn't give back ownership of the removed elements.
v.drain(..).filter(condition).collect()
returns the correct value for drained
but empties the whole vector.
Not in stable Rust 1.33.0. There's an unstable nightly feature called drain_filter
that does exactly what you want:
#![feature(drain_filter)] fn main() { let mut v: Vec<i32> = vec![1, 2, 3, 4, 5, 6]; let drained: Vec<i32> = v.drain_filter(|&mut e| e % 2 == 0).collect(); assert_eq!(v, vec![1, 3, 5]); assert_eq!(drained, vec![2, 4, 6]); }
As a stable workaround, you may be able to use Iterator::partition
, but it does not reuse the memory:
fn main() { let v: Vec<i32> = vec![1, 2, 3, 4, 5, 6]; let (drained, v): (Vec<_>, Vec<_>) = v.into_iter().partition(|&e| e % 2 == 0); assert_eq!(v, vec![1, 3, 5]); assert_eq!(drained, vec![2, 4, 6]); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With