3

我正在使用 aLinkedList并且我想删除所有未通过测试的元素。但是,我遇到了错误cannot move out of borrowed content

据我了解,这是因为我正在使用&mut self,所以我无权使包含的值之一无效(即移动),即使是片刻也无权构造一个新的值列表。

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

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

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

在我的实际情况下,我不能简单地使用包装对象,因为它需要从不同的地方引用并包含其他重要值。

在我的研究中,我发现了一些不安全的代码,这让我质疑是否可以构造一个安全的函数来以类似于std::mem::replace.

4

2 回答 2

3

您可以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();
}
于 2017-10-29T07:38:17.013 回答
0

如果目标不是克隆,您可以使用引用计数指针: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);
}
于 2017-10-29T08:28:56.720 回答