Home [Rust] Struct std::collections::HashMap 정리
Post
Cancel
Preview Image

[Rust] Struct std::collections::HashMap 정리

오늘은 rustlings 의 exercices에서 collections에 있는 hashmap 문제를 통해서

간단히 Struct std::collections::HashMap 을 정리해보겠다.

생성

먼저 다음은 hashmap1.rs 문제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use std::collections::HashMap;

fn fruit_basket() -> HashMap<String, u32> {
    let mut basket = // TODO: declare your hash map here.

    // Two bananas are already given for you :)
    basket.insert(String::from("banana"), 2);

    // TODO: Put more fruits in your basket here.

    basket
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn at_least_three_types_of_fruits() {
        let basket = fruit_basket();
        assert!(basket.len() >= 3);
    }

    #[test]
    fn at_least_five_fruits() {
        let basket = fruit_basket();
        assert!(basket
            .values()
            .sum::<u32>() >= 5);
    }
}

HashMap은 우선

1
use std::collections::HashMap;

를 통해서 사용해야 한다.

만약 해당 부분이 없다면, 다음과 같은 에러가 발생한다.

1
error[E0433]: failed to resolve: use of undeclared type `HashMap`

그 뒤,

1
let mut basket = HashMap::new();

를 통해서 HashMap을 생성해준다.

그리고 안에 데이터를 삽입해주고 싶으면,

1
2
// Two bananas are already given for you :)
basket.insert(String::from("banana"), 2);

insert를 통해서 삽입해주면 된다.

따라서 아래와 같이 코드 작성해주면 문제는 풀린다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn fruit_basket() -> HashMap<String, u32> {
    // TODO: declare your hash map here.
    let mut basket = HashMap::new();
    // let mut basket: HashMap<String, u32> = HashMap::new(); // TODO: declare your hash map here.

    // Two bananas are already given for you :)
    basket.insert(String::from("banana"), 2);

    // TODO: Put more fruits in your basket here.
    basket.insert(String::from("apple"), 3);
    basket.insert(String::from("grape"), 4);
    basket.insert(String::from("pear"), 5);

    basket
}

그런데 위와 같이 HashMap에 타입을 명시해주지 않는다면, 실수로 다른 타입을 넣어줄 수 있다.

예를 들어

1
basket.insert(5, 5);

같이 다른 타입을 넣어주면 어떻게 될까?

그럼 다음과 같은 에러가 발생한다.

1
2
3
4
5
6
7
8
9
10
11
⚠️  Compiling of exercises/collections/hashmap1.rs failed! Please try again. Here's the output:
error[E0308]: mismatched types
  --> exercises/collections/hashmap1.rs:32:19
   |
32 |     basket.insert(5, 5);
   |                   ^
   |                   |
   |                   expected struct `String`, found integer
   |                   help: try using a conversion method: `5.to_string()`

error: aborting due to previous error

알아서 컴파일 단계에서 에러를 체크해준다.

하지만 코드를 많이 작성하고 저런 컴파일 에러를 보게 되면… 화가 날 수 있으니

다음과 같이 HashMap의 타입을 명시해주면 좋다.

1
2
3
4
5
let mut basket: HashMap<String, u32> = HashMap::new();

// or

let mut basket = HashMap::<String, u32>::new();

contains_key

다음은 hashmap2.rs 문제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::collections::HashMap;

#[derive(Hash, PartialEq, Eq)]
enum Fruit {
    Apple,
    Banana,
    Mango,
    Lichi,
    Pineapple,
}

fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
    let fruit_kinds = vec![
        Fruit::Apple,
        Fruit::Banana,
        Fruit::Mango,
        Fruit::Lichi,
        Fruit::Pineapple,
    ];

    for fruit in fruit_kinds {
        // TODO: Put new fruits if not already present. Note that you
        // are not allowed to put any type of fruit that's already
        // present!
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn get_fruit_basket() -> HashMap<Fruit, u32> {
        let mut basket = HashMap::<Fruit, u32>::new();
        basket.insert(Fruit::Apple, 4);
        basket.insert(Fruit::Mango, 2);
        basket.insert(Fruit::Lichi, 5);

        basket
    }

    #[test]
    fn test_given_fruits_are_not_modified() {
        let mut basket = get_fruit_basket();
        fruit_basket(&mut basket);
        assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4);
        assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2);
        assert_eq!(*basket.get(&Fruit::Lichi).unwrap(), 5);
    }

    #[test]
    fn at_least_five_types_of_fruits() {
        let mut basket = get_fruit_basket();
        fruit_basket(&mut basket);
        let count_fruit_kinds = basket.len();
        assert!(count_fruit_kinds == 5);
    }

    #[test]
    fn greater_than_eleven_fruits() {
        let mut basket = get_fruit_basket();
        fruit_basket(&mut basket);
        let count = basket
            .values()
            .sum::<u32>();
        assert!(count > 11);
    }
}

get_fruit_basket 함수를 보면,

1
2
3
4
5
6
7
8
fn get_fruit_basket() -> HashMap<Fruit, u32> {
  let mut basket = HashMap::<Fruit, u32>::new();
    basket.insert(Fruit::Apple, 4);
    basket.insert(Fruit::Mango, 2);
    basket.insert(Fruit::Lichi, 5);

    basket
}

HashMap::<Fruit, u32>::new(); 꼴인걸 알 수 있으며,

해당 basket에 없는 Fruit 타입을 확인하고, 넣어주면 된다.

contains_keyHashMap에서 Key가 포함되어있는지 확인하는 함수이다.

따라서 for loop 안에 다음과 같이 체크하고 넣어주면 된다.

1
2
3
4
5
for fruit in fruit_kinds {
    if (!basket.contains_key(&fruit)) {
        basket.insert(fruit, 1);
    }
}

그 외 볼만한 함수들

간단하게 링크만 남기고 나중에 찾아봐야겠다.

nightly-only는 나중에 없어질 수 있으니 잠시 빼두겠다.

References

rustlings

HashMap

Solution

This post is licensed under CC BY 4.0 by the author.

[Netflix] 에놀라 홈즈 반 토막 후기

DAG가 뭔가요? 🤔