홈강좌Rust 입문·중급 47편 중 29편째
Rust HashMap — 이름(키)으로 값을 찾는 표
Rust 의 HashMap 은 키와 값을 짝지어 담고, 키로 값을 찾는 표다. use std::collections::HashMap; 으로 불러와야 하고, 빠뜨리면 E0433 이 난다. insert 로 넣고, get 은 Option 을 돌려준다. entry(…).or_insert(0) 으로 단어 수를 셀 수 있다.
01 use 로 불러온다
과일 재고를 이름으로 찾는 표를 만들어 보자. 먼저 use 없이 써 본다.
fn main() {
let mut stock = HashMap::new();
stock.insert("apple", 3);
println!("{:?}", stock.get("apple"));
}error[E0433]: cannot find type `HashMap` in this scope
--> src/main.rs:2:21
|
2 | let mut stock = HashMap::new();
| ^^^^^^^ use of undeclared type `HashMap`
|
help: consider importing this struct
|
1 + use std::collections::HashMap;- 무엇 — 이 범위에서
HashMap이라는 타입을 찾을 수 없다. - 어디 — 2번째 줄의
HashMap. - 고치는 법 —
help:가 1번째 줄에use std::collections::HashMap;을 더하라고 한다(+줄).
Vec·String·Option 은 워낙 자주 써서 처음부터 불러와져 있다. HashMap 은 아니라서 use 로 "표준 라이브러리(std)의 collections 안에 있는 HashMap" 을 불러온다. 파일 맨 위에 둔다.
02 넣고 찾는다
use std::collections::HashMap;
fn main() {
let mut stock = HashMap::new();
stock.insert("apple", 3);
stock.insert("pear", 5);
stock.insert("apple", 7);
println!("{:?}", stock.get("apple"));
println!("{:?}", stock.get("grape"));
println!("kinds: {}", stock.len());
} Compiling stock v0.1.0 (~/projects/stock)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/stock`
Some(7)
None
kinds: 2insert(키, 값)으로 넣는다. 고치는 것이니let mut다.- 같은 키로 다시 넣으면 덮어쓴다.
apple은 3 이었다가 7 이 됐다. 그래서 종류(len())는 2 다. get(키)는 28편의Vec::get처럼Option을 돌려준다. 있으면Some(7), 없는grape는None이다.
HashMap 은 넣은 순서를 기억하지 않는다. 통째로 찍으면 실행할 때마다 순서가 달라질 수 있다. 순서가 중요하면 Vec 을 쓴다.
03 실습 — 단어 수 세기
문장에서 단어마다 몇 번 나왔는지 세어 보자. 34편에서 만들 프로그램의 핵심이다.
use std::collections::HashMap;
fn main() {
let text = "the cat and the dog and the bird";
let mut counts = HashMap::new();
for word in text.split_whitespace() {
let count = counts.entry(word).or_insert(0);
*count = *count + 1;
}
println!("the: {:?}", counts.get("the"));
println!("and: {:?}", counts.get("and"));
println!("cat: {:?}", counts.get("cat"));
println!("fish: {:?}", counts.get("fish"));
} Compiling words v0.1.0 (~/projects/words)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s
Running `target/debug/words`
the: Some(3)
and: Some(2)
cat: Some(1)
fish: Nonetext.split_whitespace()는 문장을 빈칸 기준으로 잘라 단어를 하나씩 꺼낸다.for로 돈다.counts.entry(word)는 그 단어의 칸을 찾는다..or_insert(0)은 칸이 없으면 0 으로 새로 만든다. 그리고 그 칸의 값을 고칠 수 있는 참조(&mut)를 돌려준다.*count = *count + 1;은 28편의*s처럼, 참조가 가리키는 값에 1 을 더한다.
the 는 3 번, and 는 2 번, cat 은 1 번이고, 문장에 없는 fish 는 None 이다. entry 를 쓰지 않으면 "이미 있나 → 있으면 더하고 없으면 넣는다" 를 match 로 길게 써야 한다. text 를 다른 문장으로 바꿔 돌려 보자. 다음 편부터는 에러를 다룬다. 첫 번째는 panic! 과 Result 다.