How to search and embed in HashMap effectively?

I would like to do the following:

  • Find Vec for a specific key and save it for future use.
  • If this does not exist, create an empty Vec key for the key, but save it in a variable.

How to do it effectively? 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<isize> = match map.get(key) { Some(v) => v, None => { let default: Vec<isize> = Vec::new(); map.insert(key, default); &default } }; 

When I tried, he 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<isize> = 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 doing something similar, but I don’t like the fact that it searches 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<isize> = Vec::new(); map.insert(key, default); } let values: &Vec<isize> = match map.get(key) { Some(v) => v, None => { panic!("impossiburu!"); } }; 

Is there a safe way to do this in just one match ?

+45
hashmap lookup rust
Feb 14 '15 at 4:23
source share
1 answer

An entry API has been developed for this. In manual mode, it may look like

 use std::collections::hash_map::Entry; let values: &Vec<isize> = match map.entry(key) { Entry::Occupied(o) => o.into_mut(), Entry::Vacant(v) => v.insert(default) }; 

Or you can use a shorter form:

 map.entry(key).or_insert_with(|| default) 

If default is ok / cheap to calculate, even if it is not inserted, it could also be:

 map.entry(key).or_insert(default) 
+57
Feb 14 '15 at 4:41
source share



All Articles