2024-05-06 20:40:05 +00:00
|
|
|
---
|
2024-10-30 17:04:36 +00:00
|
|
|
date: 20200915
|
2024-05-06 20:40:05 +00:00
|
|
|
id: 2b38c21d-4971-42fb-9b87-5d68468e95e0
|
|
|
|
title: Rust Hash Maps
|
|
|
|
---
|
|
|
|
|
|
|
|
# Description
|
|
|
|
|
|
|
|
The type `HashMap<K, V>` stores a mapping of keys of type `K` to values
|
|
|
|
of type `V`. It does this via a hashing function, which determines how
|
|
|
|
it places these keys and values into memory. Many programming languages
|
|
|
|
support this kind of data structure, but they often use a different
|
|
|
|
name, such as hash, map, object, hash table, dictionary, or associative
|
|
|
|
array, just to name a few.
|
|
|
|
|
|
|
|
## Creating a New Hash Maps
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let mut scores = HashMap::new();
|
|
|
|
|
|
|
|
scores.insert(String::from("Blue"), 10);
|
|
|
|
scores.insert(String::from("Yellow"), 50);
|
|
|
|
|
|
|
|
println!("{}", scores["Blue"])
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### collect
|
|
|
|
|
|
|
|
Another way of constructing a hash map is by using iterators and the
|
|
|
|
[collect](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect)
|
|
|
|
method on a vector of tuples, where each tuple consists of a key and its
|
|
|
|
value.
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let teams = vec![String::from("Blue"), String::from("Yellow")];
|
|
|
|
let initial_scores = vec![10, 50];
|
|
|
|
|
|
|
|
let scores: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect();
|
|
|
|
|
|
|
|
println!("{}", scores["Blue"])
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Ownership
|
|
|
|
|
|
|
|
For types that implement the `Copy` trait, like `i32`, the values are
|
|
|
|
copied into the hash map. For owned values like `String`, the values
|
|
|
|
will be moved and the hash map will be the owner of those values:
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let field_name = String::from("Favorite color");
|
|
|
|
let field_value = String::from("Blue");
|
|
|
|
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
map.insert(field_name, field_value);
|
|
|
|
// field_name and field_value are invalid at this point
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Accessing values
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let mut scores = HashMap::new();
|
|
|
|
|
|
|
|
scores.insert(String::from("Blue"), 10);
|
|
|
|
scores.insert(String::from("Yellow"), 50);
|
|
|
|
|
|
|
|
for (key, value) in &scores {
|
|
|
|
println!("{}: {}", key, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Updating
|
|
|
|
|
|
|
|
### Overwriting a Value
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let mut scores = HashMap::new();
|
|
|
|
|
|
|
|
scores.insert(String::from("Blue"), 10);
|
|
|
|
scores.insert(String::from("Blue"), 25);
|
|
|
|
|
|
|
|
println!("{:?}", scores);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Inserting a value only if the Key has no value
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let mut scores = HashMap::new();
|
|
|
|
scores.insert(String::from("Blue"), 10);
|
|
|
|
|
|
|
|
scores.entry(String::from("Yellow")).or_insert(50);
|
|
|
|
scores.entry(String::from("Blue")).or_insert(50);
|
|
|
|
|
|
|
|
println!("{:?}", scores);
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Updating a value based on the old value
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
fn main() {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
let text = "hello world wonderful world";
|
|
|
|
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
|
|
|
|
for word in text.split_whitespace() {
|
|
|
|
let count = map.entry(word).or_insert(0);
|
|
|
|
*count += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("{:?}", map);
|
|
|
|
}
|
|
|
|
```
|