Noob to Rust and trying to figure out the idomatic way to decrement the value from a hashmap and remove the corresponding key when the value after decrementing reaches 0. I am doing it like this but not sure if its the best way to do it:
use std::collections::HashMap;
fn main() {
let mut frequency = HashMap::from([(2, 1), (3, 4), (5, 6)]);
let key = 2;
if let Some(val) = frequency.get_mut(&key) {
*val -= 1;
if *val == 0 {
frequency.remove(&key);
}
}
println!("{:?}", frequency);
}
The other I thought of is to use match construct on the value as below:
use std::collections::HashMap;
fn main() {
let mut frequency = HashMap::from([(2, 1), (3, 4), (5, 6)]);
let key = 2;
if let Some(val) = frequency.get_mut(&key) {
match *val {
1 => {
frequency.remove(&key);
}
_ => *val -= 1,
}
}
println!("{:?}", frequency);
}
I don't think there's an idiomatic way for using if
or match
. Readability is most important, so this may be your personal choice.
However, in both cases you should use entry()
to avoid doing the lookup twice:
let mut frequency = HashMap::from([(2, 1), (3, 4), (5, 6)]);
if let Entry::Occupied(mut o) = frequency.entry(2) {
*o.get_mut() -= 1;
if *o.get() == 0 {
o.remove_entry();
}
}
Using entry
, you can even match the result directly using guards:
match frequency.entry(2) {
Entry::Occupied(o) if *o.get() == 1 => {
o.remove_entry();
}
Entry::Occupied(mut o) => *o.get_mut() -= 1,
Entry::Vacant(_) => (),
};