有没有办法根据谓词排出向量的部分?

时间:2017-10-09 16:50:42

标签: vector rust predicate

我正在尝试从矢量中删除一些基于谓词的元素,并收集结果。这是一个具有预期结果的(不工作)示例:

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

这会导致错误

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();
  |                                                                ^^^^^

我看了几个替代方案,似乎没有一个做我想做的事情:

  • Vec::retain从向量中删除元素,但不会返回已删除元素的所有权。

  • v.drain(..).filter(condition).collect()会返回drained的正确值,但会清空整个矢量。

1 个答案:

答案 0 :(得分:11)

不稳定Rust 1.33.0。有一个名为drain_filter的不稳定的夜间功能,可以完全按照您的要求执行:

#![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]);
}

作为一种稳定的解决方法,您可以使用Iterator::partition,但它不会重复使用内存:

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