Обновление объектов внутри коллекции Rust - PullRequest
0 голосов
/ 10 ноября 2019

Я хотел бы изменить объекты, хранящиеся в коллекции Rust (BTreeSet).

Я хочу добиться чего-то вроде следующего здесь :

use std::collections::BTreeSet;

#[derive(Eq, PartialEq, Ord, PartialOrd, Debug)]
struct X {
    key: String,
    val: Option<i32>,
}

fn main() {

    let mut set: BTreeSet<X> = BTreeSet::new();
    set.insert(X {
        key: "a".to_string(),
        val: Some(1),
    });
    set.insert(X {
        key: "b".to_string(),
        val: Some(1),
    });

    nonify(&mut set, "a".to_string());

    println!("{:?}", set);
}

fn nonify(set: &mut BTreeSet<X>, k: String) {
    for mut s in set.iter() {
        if s.key == k {
            s.val = None;
        }
    }
}

Thisне работает, потому что s не является изменяемой ссылкой.

Как мне сделать что-то подобное в ржавчине?

Ответы [ 2 ]

5 голосов
/ 10 ноября 2019

Небезопасно (с точки зрения логики программы) изменять объекты в BTreeSet так, что их порядок изменяется, поскольку это нарушит внутреннюю структуру набора - вот фрагмент из соответствующей документации :

Логическая ошибка для элемента, который должен быть изменен таким образом, что порядок элемента относительно любого другого элемента, определяемый чертой Ord, изменяется, пока он находится вустановлен. Обычно это возможно только через Cell, RefCell, глобальное состояние, ввод / вывод или небезопасный код.

Я не знаю ваш точный вариант использования, но так как вы, похоже, используете значение ключапары, здесь могут работать HashMap или BTreeMap : они не позволяют изменять ключи по той же причине, но значения, связанные с ключами, могут быть изменены.

2 голосов
/ 10 ноября 2019

Если вы хотите изменить то, что Rust не позволяет вам изменить, вы используете RefCell. Что-то вроде this :

struct X {
    key: String,
    val: RefCell<Option<i32>>,
}

Затем для создания значения:

    val: RefCell::new(Some(1)),

И для его изменения:

fn nonify(set: &mut BTreeSet<X>, k: String) {
    for s in set.iter() {
        if s.key == k {
            *s.val.borrow_mut() = None;
        }
    }
}

Нообратите внимание, что, как предупреждал @apemanzilla в другом ответе, вы не должны изменять объекты так, чтобы их порядок изменился.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...