问题
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 fordrained
but empties the whole vector.
回答1:
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]);
}
来源:https://stackoverflow.com/questions/46651354/is-there-a-way-to-drain-parts-of-a-vector-based-on-a-predicate