I can't find a suitable way to return the exact value of key in a HashMap
in Rust . All the existing get
methods return in a different format rather than the exact format.
You probably want the HashMap::remove
method - it deletes the key from the map and returns the original value rather than a reference:
use std::collections::HashMap;
struct Thing {
content: String,
}
fn main() {
let mut hm: HashMap<u32, Thing> = HashMap::new();
hm.insert(
123,
Thing {
content: "abc".into(),
},
);
hm.insert(
432,
Thing {
content: "def".into(),
},
);
// Remove object from map, and take ownership of it
let value = hm.remove(&432);
if let Some(v) = value {
println!("Took ownership of Thing with content {:?}", v.content);
};
}
The get
methods must return a reference to the object because the original object can only exist in one place (it is owned by the HashMap
). The remove
method can return the original object (i.e "take ownership") only because it removes it from its original owner.
Another solution, depending on the specific situation, may be to take the reference, call .clone()
on it to make a new copy of the object (in this case it wouldn't work because Clone
isn't implemented for our Thing
example object - but it would work if the value way, say, a String
)
Finally it may be worth noting you can still use the reference to the object in many circumstances - e.g the previous example could be done by getting a reference:
use std::collections::HashMap;
struct Thing {
content: String,
}
fn main() {
let mut hm: HashMap<u32, Thing> = HashMap::new();
hm.insert(
123,
Thing {
content: "abc".into(),
},
);
hm.insert(
432,
Thing {
content: "def".into(),
},
);
let value = hm.get(&432); // Get reference to the Thing containing "def" instead of removing it from the map and taking ownership
// Print the `content` as in previous example.
if let Some(v) = value {
println!("Showing content of referenced Thing: {:?}", v.content);
}
}
There are two basic methods of obtaining the value for the given key: get()
and get_mut()
. Use the first one if you just want to read the value, and the second one if you need to modify the value:
fn get(&self, k: &Q) -> Option<&V>
fn get_mut(&mut self, k: &Q) -> Option<&mut V>
As you can see from their signatures, both of these methods return Option
rather than a direct value. The reason is that there may be no value associated to the given key:
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.get(&1), Some(&"a")); // key exists
assert_eq!(map.get(&2), None); // key does not exist
If you are sure that the map contains the given key, you can use unwrap()
to get the value out of the option:
assert_eq!(map.get(&1).unwrap(), &"a");
However, in general, it is better (and safer) to consider also the case when the key might not exist. For example, you may use pattern matching:
if let Some(value) = map.get(&1) {
assert_eq!(value, &"a");
} else {
// There is no value associated to the given key.
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With