Reputation: 153
Consider the following code (minimum example):
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(&3).unwrap() += map[i];
}
}
The borrow checker will complain that:
cannot borrow `map` as mutable because it is also borrowed as immutable
However, in this case I can be sure that the mutation I am doing is not interfering with the immutable references. For Vec
, I would use split_at_mut
here - is there an equivalent for that for HashMap
in Rust?
Edit:
As a comment pointed out, let me be more specific about the problem I am trying to solve. I want to implement "merging" vertices in a graph into one vertex. For this I created a HashMap
:
pub mergedVerticesList: HashMap<usize, HashSet<usize>>
which should map from a vertex to all the vertices that have been merged into that vertex. Since this can be done recursively, when undoing a merge between u
and merge_onto
I want to remove all vertices that have been merged into merge_onto
because of u
from merge_onto
's HashSet
. Thus, the code looks like this:
for i in self.mergedVerticesList[v].iter() {
self.mergedVerticesList.get_mut(&merge_onto).unwrap().remove(i);
}
Upvotes: 2
Views: 386
Reputation: 16475
No, this is not possible as far as the HashMap
is concerned. You could have cells as values to regain mutable access but I'd strongly advise against that. Can't you move the change out of the loop (it also saves from a repeated lookup per iteration). Something to the tune of
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(&3).unwrap() += s;
println!("{:#?}", &map)
}
Upvotes: 5