如何通过获取可变变量的值来替换它的价值?
我正在使用 LinkedList
,我想删除所有未通过测试的元素。但是,我遇到错误无法移出借来的内容
。
I am working with a LinkedList
and I want to remove all elements which do not pass a test. However, I am running into the error cannot move out of borrowed content
.
据我所知,这是因为我正在使用& mut self
,所以我没有权利使一个包含的值无效(即移动),甚至片刻构建一个新的列表它的值。
From what I understand, this is because I am working with &mut self
, so I do not have the right to invalidate (i.e. move) one of the contained values even for a moment to construct a new list of its values.
在C ++ / Java中,我只是迭代列表并删除任何符合条件的元素。由于我没有找到删除,我将其解释为迭代,过滤和收集。
In C++/Java, I would simply iterate the list and remove any elements which match a criteria. As there is no remove that I have yet found, I have interpreted it as an iterate, filter, and collect.
目标是避免创建临时列表,克隆值,并需要 self
并返回一个新对象。我构建了一个产生相同错误的例子。 游乐场。
The goal is to avoid creating a temporary list, cloning values, and needing take self
and return a "new" object. I have constructed an example which produces the same error. Playground.
use std::collections::LinkedList;
#[derive(Debug)]
struct Example {
list: LinkedList<i8>,
// Other stuff here
}
impl Example {
pub fn default() -> Example {
let mut list = LinkedList::new();
list.push_back(-5);
list.push_back(3);
list.push_back(-1);
list.push_back(6);
Example { list }
}
// Simmilar idea, but with creating a new list
pub fn get_positive(&self) -> LinkedList<i8> {
self.list.iter()
.filter(|&&x| x > 0)
.map(|x| x.clone())
.collect()
}
// Now, attempt to filter the elements without cloning anything
pub fn remove_negative(&mut self) {
self.list = self.list.into_iter()
.filter(|&x| x > 0)
.collect()
}
}
fn main() {
let mut e = Example::default();
println!("{:?}", e.get_positive());
println!("{:?}", e);
}
在我的实际情况中,我不能简单地使用包装对象,因为它需要从不同的地方引用并包含其他重要的值。
In my actual case, I cannot simply consume the wrapping object because it needs to be referenced from different places and contains other important values.
在我的研究中,我发现了一些不安全代码,这让我质疑是否可以构建一个安全函数来执行此操作,其方式与 std :: mem :: replace
。
In my research, I found some unsafe code which leads me to question if a safe function could be constructed to perform this action in a similar way to std::mem::replace
.
您可以 std :: mem :: swap
带有临时值的字段,然后将其替换为您修改后的列表像这样。最大的缺点是创建了新的LinkedList。我不知道它有多贵。
You can std::mem::swap
your field with a temp, and then replace it with your modified list like this. The big downside is the creation of the new LinkedList. I don't know how expensive that is.
pub fn remove_negative(&mut self) {
let mut temp = LinkedList::new();
std::mem::swap(&mut temp, &mut self.list);
self.list = temp.into_iter()
.filter(|&x| x > 0)
.collect();
}