【发布时间】:2018-04-10 05:36:11
【问题描述】:
我正在使用LinkedList,我想删除所有未通过测试的元素。但是,我遇到了错误cannot move out of borrowed content。
据我了解,这是因为我正在使用&mut self,因此我无权使包含的值之一无效(即移动),即使是片刻也无权构造一个新的值列表。
在 C++/Java 中,我会简单地迭代列表并删除任何符合条件的元素。由于我还没有找到删除,我将其解释为迭代、过滤和收集。
目标是避免创建临时列表、克隆值以及需要采用self 并返回“新”对象。我构建了一个产生相同错误的示例。 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);
}
在我的实际情况中,我不能简单地使用包装对象,因为它需要从不同的地方引用并包含其他重要值。
在我的研究中,我发现了一些unsafe code,这让我质疑是否可以构造一个安全函数来以类似于std::mem::replace 的方式执行此操作。
【问题讨论】:
-
如果它被转换成一个通用(安全)函数——这样的通用安全函数是遥不可及的。由于该代码最初来自 Stack Overflow,因此我更新了您的链接;它现在指向代码的版本,其中充斥着关于它在哪些条件下有效的警告。
-
您的文字似乎在谈论您的真实世界示例,而您的代码只是(或多或少)最小示例(这很好!)。但也许您可以编辑文本以匹配您的代码示例。这意味着:删除听众和弱指针的提及。如果我正确理解您的问题,它基本上是“如何在不创建新列表的情况下迭代链接列表的特定元素?”,对吗?
-
@LukasKalbertodt 差不多了,我包含了额外的信息,目的是解释为什么我不能简单地消费
self以及为什么我想避免克隆(后来意识到克隆并不可怕) .将简化... -
正如
LinkedList文档本身所说:几乎总是使用Vec或VecDeque而不是LinkedList和Vechas a method to do exactly what you want .现在我们必须弄清楚如何对LinkedList做同样的事情。 -
@Shepmaster 老实说,您可能是对的,我选择了 LinkedList 是因为它永远不需要按索引进行访问,并且会定期附加和过滤。
标签: collections iterator rust borrowing