Как я могу удалить членов типа коллекции на месте? - PullRequest
1 голос
/ 30 сентября 2019

Я хочу перебрать тип коллекции в структуре и удалить некоторые значения, но Rust не позволяет мне уничтожить коллекцию:

fn some_method(&mut self) {
    self.collection = self
        .collection
        .into_iter()
        .filter(/* ... */
        .collect();
}

Я мог бы клонировать все значения для создания другой коллекции, ноэто не эффективно. Какой идиоматический способ удаления значения из коллекции в Rust?

Ответы [ 2 ]

1 голос
/ 01 октября 2019

Поскольку collection является BTreeMap и не имеет .drain() или .retain, и вы можете очистить дерево во время обработки, вам нужно будет удалить дерево из self.collection манипулируйте им так, как вы хотите, а затем положите обратно.

Как вы уже видели, Rust не позволяет этого с простым присваиванием, потому что если бы была паника во время выполнения вашего фрагмента, self.collection остался бы в несогласованном состоянии. Вместо этого вам нужно сделать это явно, используя std::mem::replace, что позволяет вам взять на себя ответственность за содержимое в изменяемой ссылке, предоставляя ему замену, поэтому ссылка продолжает указывать на действительные данные.

fn some_method(&mut self) {
  self.collection = std::mem::replace(&mut self.collection, BTreeMap::new())
    .into_iter()
    .filter(|_| true)
    .collect();
}
1 голос
/ 30 сентября 2019

Полный пример (также с into_iter):

#[derive(Debug)]
struct Scores {
    collection: Vec<i32>,
}

impl Scores {
    fn new() -> Scores {
        return Scores {
            collection: Vec::new(),
        };
    }

    fn filter_in_above_50(&mut self) {
        self.collection = self
            .collection
            .drain(..)
            .filter(|score| score > &50)
            .collect();
    }

    fn filter_in_above_50_using_into_iter(&mut self) {
        let coll: &mut Vec<i32> = self.collection.as_mut();
        let coll: Vec<i32> = coll
            .into_iter()
            .filter(|score| score > &&mut 50i32)
            .map(|&mut x| x)
            .collect();
        self.collection = coll;
    }
}

И тесты:

#[test]
fn score_test() {
    let mut s = Scores::new();
    s.collection.push(199);
    s.collection.push(11);
    s.filter_in_above_50();
    assert_eq!(s.collection, vec![199]);
}

#[test]
fn score_test_using_into_iter() {
    let mut s = Scores::new();
    s.collection.push(199);
    s.collection.push(11);
    s.filter_in_above_50_using_into_iter();
    assert_eq!(s.collection, vec![199]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...