【问题标题】:How to take, transform and replace a vector in a mutable reference?如何在可变引用中获取、转换和替换向量?
【发布时间】:2021-07-04 07:52:22
【问题描述】:

我有一个struct Database { events: Vec<Event> }。我想对events 应用一些地图和过滤器。有什么好的方法可以做到这一点?

这是我尝试过的:

fn update(db: &mut Database) {
    db.events = db.events.into_iter().filter(|e| !e.cancelled).collect();
}

这不起作用:

cannot move out of `db.events` which is behind a mutable reference
...
move occurs because `db.events` has type `Vec<Event>`, which does not implement the `Copy` trait

有什么方法可以让 Rust 编译器相信我只是暂时获取字段值?

【问题讨论】:

标签: rust


【解决方案1】:

为什么这不起作用的概念问题是由于恐慌。例如,如果filter 回调发生恐慌,那么db.events 将被into_iter 移出,但不会有一个值来替换它——它将未初始化,因此不安全。

Joël Hecht 拥有您在特定实例中真正想做的事情:Vec::retain 可让您过滤掉适当的元素,并重用存储空间。

Alexey Larionov 也有一个涉及Vec::drain 的答案,它会留下一个空向量,直到发生替换。不过,它需要重新分配。

但是,在一般情况下,replace_withtake_mut 板条箱提供了帮助完成您正在做的事情的功能。您为函数提供一个闭包,该闭包接受该值并返回其替换值,并且 crates 将运行该闭包,并在出现恐慌时中止该过程。

【讨论】:

    【解决方案2】:

    在你暴露的情况下,更安全的方法是使用Vec.retain

    fn update(db: &mut Database) {
        db.events.retain(|e| !e.cancelled);
    }
    

    【讨论】:

      【解决方案3】:

      除了@Joël Hecht 的回答,您可以Vec::drain 元素然后重新创建向量。 Playground

      fn update(db: &mut Database) {
          db.events = db.events
              .drain(..)
              .filter(|e| !e.cancelled)
              .collect();
      }
      

      【讨论】:

        猜你喜欢
        • 2019-11-16
        • 2022-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-02
        • 2019-04-26
        相关资源
        最近更新 更多