Эквивалент split_at_mut для HashMap?

#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)
}