Collections 如何通过拥有可变变量的所有权来替换可变变量的值?

Collections 如何通过拥有可变变量的所有权来替换可变变量的值?,collections,iterator,rust,borrowing,Collections,Iterator,Rust,Borrowing,我正在使用LinkedList,希望删除所有未通过测试的元素。但是,我遇到了错误无法移出借用的内容 据我所知,这是因为我使用的是&mut self,因此我无权使其中一个包含的值无效(即移动),即使是在构建其值的新列表时 在C++/Java中,我只需迭代列表并删除任何符合条件的元素。由于还没有找到删除,我将其解释为迭代、筛选和收集 目标是避免创建临时列表、克隆值以及需要获取self并返回“新”对象。我构造了一个产生相同错误的示例 使用std::collections::LinkedList; #[

我正在使用
LinkedList
,希望删除所有未通过测试的元素。但是,我遇到了错误
无法移出借用的内容

据我所知,这是因为我使用的是
&mut self
,因此我无权使其中一个包含的值无效(即移动),即使是在构建其值的新列表时

在C++/Java中,我只需迭代列表并删除任何符合条件的元素。由于还没有找到删除,我将其解释为迭代、筛选和收集

目标是避免创建临时列表、克隆值以及需要获取
self
并返回“新”对象。我构造了一个产生相同错误的示例

使用std::collections::LinkedList;
#[导出(调试)]
结构示例{
列表:LinkedList,
//这里还有其他东西
}
impl示例{
pub fn default()->示例{
让mut list=LinkedList::new();
列表。推回(-5);
列表。推回(3);
列表。推回(-1);
列表。推回(6);
示例{list}
}
//类似的想法,但创建一个新的列表
pub fn get_positive(&self)->LinkedList{
self.list.iter()
.filter(|&x | x>0)
.map(| x | x.clone())
.collect()
}
//现在,尝试在不克隆任何内容的情况下筛选元素
发布fn删除\u负片(&mut self){
self.list=self.list.into_iter()
.filter(|&x | x>0)
.collect()
}
}
fn main(){
让mut e=Example::default();
println!(“{:?}”,e.get_positive());
println!(“{:?}”,e);
}
在我的实际情况中,我不能简单地使用包装对象,因为它需要从不同的位置引用,并且包含其他重要的值


在我的研究中,我发现了一些问题,这让我怀疑是否可以构造一个安全函数来以类似于的方式执行此操作。

您可以
std::mem::swap
使用临时变量替换字段,然后用这样修改过的列表替换它。最大的缺点是新LinkedList的创建。我不知道那有多贵

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();
}

如果目标不是克隆,则可以使用引用计数指针:Rc上的clone方法增加引用计数器

use std::collections::LinkedList;
use std::rc::Rc;

#[derive(Debug)]
struct Example {
    list: LinkedList<Rc<i8>>,
    // ...
}

impl Example {
    pub fn default() -> Example {
        let mut list = LinkedList::new();
        list.push_back(Rc::new(-5));
        list.push_back(Rc::new(3));
        list.push_back(Rc::new(-1));
        list.push_back(Rc::new(6));
        Example { list }
    }

    // Simmilar idea, but with creating a new list
    pub fn get_positive(&self) -> LinkedList<Rc<i8>> {
        self.list.iter()
            .filter(|&x| x.as_ref() > &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.iter()
            .filter(|&x| x.as_ref() > &0)
            .map(|x| x.clone())
            .collect()
    }


}


fn main() {
    let mut e = Example::default();
    e.remove_negative();
    println!("{:?}", e.get_positive());
    println!("{:?}", e);
}
使用std::collections::LinkedList;
使用std::rc::rc;
#[导出(调试)]
结构示例{
列表:LinkedList,
// ...
}
impl示例{
pub fn default()->示例{
让mut list=LinkedList::new();
列表。推回(Rc::new(-5));
列表。推回(Rc::new(3));
list.push_back(Rc::new(-1));
列表。推回(Rc::new(6));
示例{list}
}
//类似的想法,但创建一个新的列表
pub fn get_positive(&self)->LinkedList{
self.list.iter()
.filter(|&x | x.as_ref()>&0)
.map(| x | x.clone())
.collect()
}
//现在,尝试在不克隆任何内容的情况下筛选元素
发布fn删除\u负片(&mut self){
self.list=self.list.iter()
.filter(|&x | x.as_ref()>&0)
.map(| x | x.clone())
.collect()
}
}
fn main(){
让mut e=Example::default();
e、 移除_负片();
println!(“{:?}”,e.get_positive());
println!(“{:?}”,e);
}

如果将其转换为通用(安全)功能,则远程不可能实现此类通用安全功能。由于该代码最初来自堆栈溢出,我更新了您的链接;现在,它指向了代码的版本,其中充斥着关于它在何种条件下有效的警告。您的文本似乎在谈论您的真实示例,而您的代码只是(或多或少)一个最小的示例(这很好!)。但也许您可以编辑文本以匹配代码示例。这意味着:删除对侦听器和弱指针的提及。如果我正确理解了你的问题,基本上是“我如何在不创建新列表的情况下在迭代链表时删除链表的特定元素?”对吗?@LukasKalbertodt差不多就是这样,我加入了额外的信息,目的是解释为什么我不能简单地消费
self
,以及为什么我想避免克隆(后来意识到克隆并不可怕)。将简化…正如
LinkedList
文档本身所述:几乎总是最好使用
Vec
VecDeque
而不是
LinkedList
Vec
。现在我们必须弄清楚如何使用
LinkedList
@Shepmaster做同样的事情老实说,你可能是对的,我选择LinkedList是因为它不需要索引访问,并且会定期追加和过滤。请注意,Rust的内置集合通常有非常便宜的空状态。是的,这会起作用,是的,它不会太贵,但我试图避免它,因为从逻辑上讲,它似乎很愚蠢。例如,我们为
Vec
提供了
retain
函数,该函数完全实现了所需的功能,在另一种语言(如C++/Java)中,您可以在迭代时简单地删除元素。也就是说,我认为这可能是目前最好的解决方案,因为Rust API没有切换到
Vec
。在我的情况下,克隆是一种选择,但实际上我使用的是Arc,因此它现在会增加额外的同步开销。
use std::collections::LinkedList;
use std::rc::Rc;

#[derive(Debug)]
struct Example {
    list: LinkedList<Rc<i8>>,
    // ...
}

impl Example {
    pub fn default() -> Example {
        let mut list = LinkedList::new();
        list.push_back(Rc::new(-5));
        list.push_back(Rc::new(3));
        list.push_back(Rc::new(-1));
        list.push_back(Rc::new(6));
        Example { list }
    }

    // Simmilar idea, but with creating a new list
    pub fn get_positive(&self) -> LinkedList<Rc<i8>> {
        self.list.iter()
            .filter(|&x| x.as_ref() > &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.iter()
            .filter(|&x| x.as_ref() > &0)
            .map(|x| x.clone())
            .collect()
    }


}


fn main() {
    let mut e = Example::default();
    e.remove_negative();
    println!("{:?}", e.get_positive());
    println!("{:?}", e);
}