Это невозможно с вашей текущей структурой данных.
HashSet
преднамеренно не предоставляет методы для изменения значений.Как вы уже упоминали, изменение значения в HashSet
(или ключ в HashMap
) приведет к аннулированию хеша в большинстве случаев.API поощряет правильное использование и даже упоминает об этом:
Логическая ошибка для элемента, модифицируемого таким образом, что хеш элемента, как определено * 1010Черта * или ее равенство, определяемое чертой Eq
, изменяется, пока она находится в наборе.Обычно это возможно только через Cell
, RefCell
, глобальное состояние, ввод / вывод или небезопасный код.
Это относится к одномуТаким образом, вы можете решить свою проблему, используя внутреннюю изменчивость:
use std::cell::Cell;
#[derive(Debug, Eq)]
struct Foo {
id: Id,
other_data: Cell<u32>,
}
fn main() {
let mut baz = HashSet::new();
baz.insert(Foo {
id: 1,
other_data: Cell::new(2),
});
if let Some(x) = baz.get(&1) {
x.other_data.set(3);
}
}
Это разумная вещь, но я не был бы рад сделать это.Вместо этого я бы позволил разложить мой тип на ключ и значение и сохранить его в HashMap
, как уже упоминалось.Что-то вроде
impl Foo {
// or insert_into_hashmap(self, &mut HashMap<Id, u32>)
fn into_key_value(self) -> (Id, u32) {
(self.id, self.other_data)
}
// Maybe a
//
// fn from_key_value(&'a Id, &'a u32) -> Self
// or
// fn from_hashmap(Id, &HashMap<Id, u32>) -> Self
}
// Maybe a
//
// struct FooRef<'a> { (or FooRefMut?)
// id: &'a Id,
// other_data: &'a u32,
// }
//
// With a
// fn from_key_value(&'a Id, &'a u32) -> Self
// or
// fn from_hashmap(Id, &HashMap<Id, u32>) -> Self
fn main() {
let mut baz = HashMap::new();
let f = Foo {
id: 1,
other_data: 2,
};
let (k, v) = f.into_key_value();
baz.insert(k, v);
// See also HashMap::get_key_value
if let Some(v) = baz.get_mut(&1) {
*v = 3;
}
}