snippetrustCritical
How to lookup from and insert into a HashMap efficiently?
Viewed 0 times
insertlookuphowfromandhashmapefficientlyinto
Problem
I'd like to do the following:
How to do this efficiently? Naturally I thought I could use
When I tried it, it gave me errors like:
I ended up with doing something like this, but I don't like the fact that it performs the lookup twice (
Is there a safe way to do this with just one
- Lookup a
Vecfor a certain key, and store it for later use.
- If it doesn't exist, create an empty
Vecfor the key, but still keep it in the variable.
How to do this efficiently? Naturally I thought I could use
match:use std::collections::HashMap;
// This code doesn't compile.
let mut map = HashMap::new();
let key = "foo";
let values: &Vec = match map.get(key) {
Some(v) => v,
None => {
let default: Vec = Vec::new();
map.insert(key, default);
&default
}
};When I tried it, it gave me errors like:
error[E0502]: cannot borrow map as mutable because it is also borrowed as immutable
--> src/main.rs:11:13
|
7 | let values: &Vec = match map.get(key) {
| --- immutable borrow occurs here
...
11 | map.insert(key, default);
| ^^^ mutable borrow occurs here
...
15 | }
| - immutable borrow ends here
I ended up with doing something like this, but I don't like the fact that it performs the lookup twice (
map.contains_key and map.get):// This code does compile.
let mut map = HashMap::new();
let key = "foo";
if !map.contains_key(key) {
let default: Vec = Vec::new();
map.insert(key, default);
}
let values: &Vec = match map.get(key) {
Some(v) => v,
None => {
panic!("impossiburu!");
}
};Is there a safe way to do this with just one
match?Solution
The
One can use the briefer form via
If
If the
entry API is designed for this. In manual form, it might look likelet values = match map.entry(key) {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(default),
};
One can use the briefer form via
Entry::or_insert_with:let values = map.entry(key).or_insert_with(|| default);
If
default is already computed, or if it's OK/cheap to compute even when it isn't inserted, you can use Entry::or_insert:let values = map.entry(key).or_insert(default);
If the
HashMap's value implements Default, you can use Entry::or_default, although you may need to provide some type hints:let values = map.entry(key).or_default();
Context
Stack Overflow Q#28512394, score: 273
Revisions (0)
No revisions yet.