Removing an entry
Sometimes an entry has to go: a shop stops selling an item, or a player leaves a game. A HashMap's remove method takes the key and deletes that key together with its value.
let mut animals = HashMap::from([("cat", 4), ("dog", 2), ("rabbit", 1)]);
animals.remove("rabbit");
println!("{}", animals.len()); // 2
Deleting changes the map, so it must be declared with let mut. Calling remove on a map declared without mut is a compile error: "cannot borrow b as mutable, as it is not declared as mutable". When the key is a String in a variable called name, pass a reference: remove(&name). (In a file of your own, a HashMap needs use std::collections::HashMap;.)
What remove returns
remove hands back the deleted value inside an Option. For the rabbit that is Some(1). For a key that isn't in the map it returns None, and the map doesn't change. So removing a key twice is harmless: the first call gives Some(1) and the second gives None, with two entries left. The lesson's task ignores the returned value, and Rust accepts that.
After the delete
The length drops by 1, and animals.contains_key("rabbit") becomes false. Reading animals["rabbit"] now panics and stops the program, so check with contains_key first if the key may be gone.
The task, step by step
The shop's animals map starts with cats, dogs and one rabbit, so the first line printed is the length, 3. The last rabbit just went home with a family. The first step deletes the key with animals.remove("rabbit"), below the first println!. The second step prints animals.len() again, which is one less: 2. The code at the bottom then checks the key, and since it is gone, it prints the "No rabbits left" message.
let mut animals = HashMap::from([("cat", 4), ("dog", 2), ("rabbit", 1)]);
println!("{}", animals.len());
animals.remove("rabbit");
println!("{}", animals.len());
if animals.contains_key("rabbit") {
println!("We still have rabbits");
} else {
println!("No rabbits left");
}
It prints:
3
2
No rabbits left
Removing a key that may be missing
Because remove returns None for a key that isn't there and leaves the map alone, you don't need a contains_key check before it. You only need the check when you want to do something different depending on whether the key existed. If you do want that, the return value tells you: Some(1) means a rabbit entry existed with count 1, and None means there was nothing to remove. Compare that with indexing, where a missing key stops the program. Deleting is forgiving, and reading with [] is not.
Order of the printed lines
The task's output has three lines because the program does three things in order: print the length before the delete, delete, print the length after, then run the final check. The first number is 3 because the map has three keys. Remove does not make the other entries move or change; cat still has 4 and dog still has 2. Only the entry whose key you passed is gone, and the length is the count of keys left.
Common mistakes
- Declaring the map with
letinstead oflet mut. - Passing the value (
1) toremove. It wants the key. - Reading the key with
[]after deleting it.
Key takeaways
map.remove(key)deletes the key and its value, and needs amutmap.- It returns
Some(value)for a present key andNonefor a missing one. - After a delete,
len()is one less andcontains_keyisfalse.
