#rust #hashmap #ownership
#Ржавчина #hashmap #владение
Вопрос:
У меня есть HashMap
и я хотел бы обновить значение, если оно существует, и в противном случае добавить значение по умолчанию. Обычно я бы сделал это так:
some_map.entry(some_key)
.and_modify(|e| modify(e))
.or_insert(default)
Но теперь у меня modify
есть тип fn(T)->T
, но проверка заимствования, очевидно, не позволит мне писать:
some_map.entry(some_key)
.and_modify(|e| *e = modify(*e))
.or_insert(default)
Какой предпочтительный способ сделать это в Rust? Должен ли я просто использовать remove
and insert
?
Комментарии:
1. Я думаю, что в таком контексте, например
HashMap.entry(some_key).and_modify(f)
, вам следует сначала рассмотреть вопрос о предоставленииf
типаfn(amp;mut T)
.fn(T)->T
это просто неправильный выбор.
Ответ №1:
Предполагая, что вы можете создать пустую версию своего T
по дешевке, вы могли бы использовать mem::replace
:
some_map.entry(some_key)
.and_modify(|e| {
// swaps the second parameter in and returns the value which was there
let mut v = mem::replace(e, T::empty());
v = modify(v);
// puts the value back in and discards the empty one
mem::replace(e, v);
})
.or_insert(default)
это предполагает modify
, что вы не паникуете, в противном случае вы обнаружите, что «пустое» значение остается на вашей карте. Но у вас была бы аналогичная проблема с remove
/ insert
.
Комментарии:
1. Если пустой
T
не так просто, но вы управляете картой, переключение на aHashMap<K, Option<T>>
может помочь.2. Существует также этот
replace_with
ящик, если вы можете пойти на компромисс.