如何获取、转换和替换可变引用中的向量



我有一个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编译器我只是暂时取字段值?

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

Joël Hecht在您的特定实例中有您真正想要做的事情:Vec::retain可以让您过滤掉现有的元素,还可以重用存储。

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

然而,在一般情况下,replace_withtake_mut板条箱提供了一些功能来帮助完成您正在做的事情。您为函数提供了一个闭包,该闭包获取值并返回其替换项,板条箱将运行该闭包,如果出现恐慌,则中止该过程。

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

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

或者@Joël Hecht的答案,您可以Vec::drain元素,然后重新创建向量。游乐场

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

最新更新