【问题标题】:Removing elements from a Vec based on some condition [duplicate]根据某些条件从 Vec 中删除元素 [重复]
【发布时间】:2016-10-14 00:46:50
【问题描述】:

我的代码如下所示:

struct Bar {
    i: i32,
}

struct Foo {
    v: Vec<Bar>,
}

impl Foo {
    fn foo(&mut self) {
        self.v.drain(self.v.iter().filter(|b| b.i < 10));
    }
}

注意Bar不允许被复制或克隆。

我想删除所有不满足该条件的Bars。最初我以为我可以遍历它们并调用remove,但如果有一个完全有意义的不可变借用,我不允许有两个可变借用或一个可变借用。

我想最简单的方法是只使用clonefiltercollect,但我不允许克隆或复制。

我该怎么做?

【问题讨论】:

    标签: rust


    【解决方案1】:

    在夜间 Rust 中,您可以使用 Vec::drain_filter:

    #![feature(drain_filter)]
    
    #[derive(Debug)]
    struct Bar {
        i: i32,
    }
    
    fn main() {
        let mut bars = vec![Bar { i: 1 }, Bar { i: 10 }, Bar { i: 3 }, Bar { i: 100 }];
        bars.drain_filter(|b| b.i < 10);
        println!("{:?}", bars);
    }
    

    drain_filter 的额外有趣之处在于,当它返回它们的迭代器时,您可以获得被拒绝的值:

    let rejects: Vec<_> = bars.drain_filter(|b| b.i < 10).collect();
    

    您也可以选择修改被迭代的值:

    bars.drain_filter(|b| {
        b.i -= 1;
        b.i < 10
    });
    

    【讨论】:

      【解决方案2】:

      如果你查看Vec 的接口,你不会发现基于谓词擦除某些元素的方法。相反,您会发现 retain 基于谓词保留元素。

      当然,两者都是对称的,只是retain 更难找到如果您通过“删除”或“擦除”过滤方法名称(它的描述中确实包含“删除”)。

      提供的示例不言自明:

      let mut vec = vec![1, 2, 3, 4];
      vec.retain(|&x| x % 2 == 0);
      assert_eq!(vec, [2, 4]);
      

      【讨论】:

      • 我通过以下方式理解方法的名称:虽然“过滤器”不过滤与谓词匹配的元素,但令人困惑的是,“保留”确实保留了与谓词匹配的元素。我认为这对于新程序员来说会更直观。
      • @mako:正是因为这个原因,我也更喜欢retain。不知何故,我已经很难使用布尔值,所以如果保留/丢弃哪些元素的语义不清楚,那对我来说就更难了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多