【问题标题】:Is there a way to drain parts of a vector based on a predicate?有没有办法根据谓词排出部分向量?
【发布时间】:2017-10-09 16:50:41
【问题描述】:

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

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 返回正确的值,但会清空整个向量。

【问题讨论】:

  • 你试过用to_vec转换数组吗? let drained: Vec&lt;i32&gt; = v.iter().filter(|e| (*e) % 2 == 0).to_vec().drain(..).collect();

标签: vector rust predicate


【解决方案1】:

不在稳定的 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]);
}

【讨论】:

【解决方案2】:

文档说明 Vec.retain 将在原地运行,并按顺序访问每个元素,恰好一次。

fn drain_where<T, Pred : Fn(&T) -> bool>(source: &mut Vec<T>, pred: Pred) -> Vec<T>
  where T : Copy {
  let mut drained: Vec<T> = Vec::new();
  
  source.retain(|item| {
    if pred(item) { drained.push(*item); false } else { true }
  });
  
  drained
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 2021-10-22
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多