#rust #borrow-checker
#Ржавчина #проверка заимствования
Вопрос:
Рассмотрим следующий код (минимальный пример):
use std::collections::HashMap;
fn main() {
let mut map: HashMap<usize, i128> = HashMap::new();
map.insert(1, -5);
map.insert(2, 6);
map.insert(3, 7);
for i in map.keys() {
if *i == 3 {
continue;
}
*map.get_mut(amp;3).unwrap() = map[i];
}
}
Проверка заимствования будет жаловаться, что:
cannot borrow `map` as mutable because it is also borrowed as immutable
Однако в этом случае я могу быть уверен, что выполняемая мной мутация не мешает неизменяемым ссылкам. Например Vec
, я бы использовал split_at_mut
здесь — есть ли эквивалент для этого HashMap
в Rust?
Редактировать:
Как указано в комментарии, позвольте мне более конкретно рассказать о проблеме, которую я пытаюсь решить. Я хочу реализовать «слияние» вершин в графе в одну вершину. Для этого я создал HashMap
:
pub mergedVerticesList: HashMap<usize, HashSet<usize>>
который должен отображаться из вершины во все вершины, которые были объединены в эту вершину. Поскольку это можно сделать рекурсивно, при отмене слияния между u
и merge_onto
я хочу удалить все вершины, которые были объединены из merge_onto
-за u
from merge_onto
‘s HashSet
. Таким образом, код выглядит следующим образом:
for i in self.mergedVerticesList[v].iter() {
self.mergedVerticesList.get_mut(amp;merge_onto).unwrap().remove(i);
}
Комментарии:
1. В чем на самом деле проблема, которую вы пытаетесь решить здесь? У меня такое чувство, что это пример проблемы XY , и что могут быть лучшие способы решения реальной проблемы вместо того, что вы пытаетесь сделать здесь.
2. Спасибо, это хороший момент. Я отредактировал вопрос, чтобы, надеюсь, сделать его более понятным.
Ответ №1:
Нет, это невозможно, насколько HashMap
это касается. Вы могли бы использовать ячейки в качестве значений для восстановления изменяемого доступа, но я бы настоятельно не советовал этого делать. Разве вы не можете переместить изменение из цикла (это также избавляет от повторного поиска за итерацию). Что-то вроде
use std::collections::HashMap;
fn main() {
let mut map: HashMap<usize, i128> = HashMap::new();
map.insert(1, -5);
map.insert(2, 6);
map.insert(3, 7);
let s = map.iter().filter_map(|(k, v)| if *k != 3 { Some(v) } else { None }).sum::<i128>();
*map.get_mut(amp;3).unwrap() = s;
println!("{:#?}", amp;map)
}