隱私權政策

搜尋此網誌

技術提供:Blogger.

關於我自己

我的相片
目前從事軟體相關行業,喜歡閱讀、健身、喝調酒。習慣把遇到的問題記下來,每天做一些整理方便自己以後查。 Python、Rust、Kotlin等程式語言皆為自學,目前比較著重在Rust語言,歡迎一起討論。

2023年12月19日 星期二

Rust HashMap概述2 - get、get_key_value、雙重HashMap


HashMap 2

上一篇[1]有提到HashMap的用法

這篇繼續

這篇主要會提到get、get_key_value、以及HashMap的value也是一個HashMap的用法


另外除了用HashMap::new創建HashMap以外

HashMap::from也可以

舉一個簡單的範例程式

use std::collections::HashMap;

fn main() {
    let score_map: HashMap<&str, u8> = HashMap::from([("Chinese", 64), ("Math", 58)]);
    let chinese_score: &u8 = score_map.get("Chinese").unwrap();
    let math: (&&str, &u8) = score_map.get_key_value("Math").unwrap();
    println!("{:?}", score_map);
    println!("Chinese score: {:?}", chinese_score);
    println!("{:?}", math);
}
{"Math": 58, "Chinese": 64} Chinese score: 64 ("Math", 58)


稍微講一下有用到的方法

HashMap::from[2]

fn from(arr: [(K, V); N]) -> Self

透過HashMap::from可以創建HashMap

做法是HashMap::from後方接著打[(Key1, Value1), (Key2, Value2), ...]

如同上方程式

HashMap::from([("Chinese", 64), ("Math", 58)])

把Chinese和64分連結,Math和58分連結


get[3]

pub fn get<Q>(&self, k: &Q) -> Option<&V>
where
    K: Borrow<Q>,
    Q: Hash + Eq + ?Sized,

get為輸入key值

可以獲得Option value

也就是可以獲得對應Key的Value

但輸出為Option,需要unwrap


get_key_value[4]

pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where
    K: Borrow<Q>,
    Q: Hash + Eq + ?Sized,

跟get很像

一樣輸入key

但輸出會連同key和value一起輸出

一樣是Option,但這次輸出是元組(tuple)[5]

而如果需要單獨使用裡面的值

    println!("{}: {}", math.0, math.1);
Math: 58

math.0表示元組第一個,math.1表示元組第二個


雙重HashMap例子

而最近打程式有題目是要用到雙重HashMap

也就是有一個HashMap後

第一個HashMap的value也是一個HashMap

舉個實際情況

假設班上有很多學生

並且有國文、英文、數學三個科目

每個科目每學期都有一堆考試

要將其分類

這時候就可以用到雙重HashMap

第一個HashMap放學生姓名和另一個HashMap

另一個HashMap則是科目和成績,成績用數組表示

也就是用程式可以這樣打

use std::collections::HashMap;

struct Score {
    name: String,
    subject: String,
    score: u8,
}
impl Score {
    fn new(name: &str, subject: &str, score: u8) -> Score{
        Score{
            name: name.to_string(),
            subject: subject.to_string(),
            score
        }
    }
}
fn main() {
    let student_score = vec![
        Score::new("Alex", "Chinese", 90),
        Score::new("Alex", "Math", 80),
        Score::new("Alex", "Chinese", 50),
        Score::new("Alex", "English", 20),
        Score::new("Alex", "Chinese", 30),
        Score::new("Alex", "Math", 10),
        Score::new("Berry", "Chinese", 20),
        Score::new("Berry", "Chinese", 10),
        Score::new("Berry", "Math", 55),
        Score::new("Berry", "Chinese", 67),
        Score::new("Berry", "English", 29),
        Score::new("Berry", "Math", 92),
        Score::new("Caitlyn", "English", 76),
        Score::new("Caitlyn", "Math", 58),
        Score::new("Caitlyn", "Chinese", 79),
        Score::new("Caitlyn", "Chinese", 0),
        Score::new("Caitlyn", "Chinese", 32),
        Score::new("Caitlyn", "Math", 100),
    ];
    let mut student_score_map: HashMap<String, HashMap<String, Vec<u8>>>
                                                                = HashMap::new();
    for score in student_score {
        let name_entry = student_score_map.entry(score.name).or_insert(HashMap::new());
        let subject_entry = name_entry.entry(score.subject).or_insert(vec![]);
        subject_entry.push(score.score);
    }
    println!("{:?}", student_score_map);
}

首先struct Score是先設定學生們的姓名、科目、分數

並透過impl裡面的fn new()紀錄

一開始分數放在student_score,裡面是亂的

先創建一個名為student_score_map的HashMap

資料型態為String與第二個HashMap

第二個HashMap負責放科目和分數


要獲得HashMap裡面的值都會運用到entry

先判定有沒有學生的名字,如果沒有則放入HashMap

再來判定學生有沒有這個科目,如果沒有則放入vec!

最後要將分數(value)放入科目(key),再把它對應學生姓名(key)

輸出

{"Alex": {"Chinese": [90, 50, 30], "Math": [80, 10], "English": [20]},
"Berry": {"Chinese": [20, 10, 67], "Math": [55, 92], "English": [29]},
"Caitlyn": {"English": [76], "Math": [58, 100], "Chinese": [79, 0, 32]}}


那如果想要把所有學生的國文成績都單獨印出來呢?

    for (name, subject_score) in student_score_map {
        let chinese_socre = subject_score.get_key_value("Chinese").unwrap();
        println!("{}, {}: {:?}", name, chinese_socre.0, chinese_socre.1 );
    }
Berry, Chinese: [20, 10, 67] Caitlyn, Chinese: [79, 0, 32] Alex, Chinese: [90, 50, 30]

透過get_key_value把Chinese和其分數抓出來

並且輸出即可


參考資料

[1] https://lageeblog.blogspot.com/2023/12/rust-hashmap-keyvalue.html

[2] https://doc.rust-lang.org/std/collections/struct.HashMap.html#impl-From%3C%5B(K,+V);+N%5D%3E-for-HashMap%3CK,+V,+RandomState%3E

[3] https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get

[4] https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_key_value

[5] https://rustwiki.org/zh-CN/rust-by-example/primitives/tuples.html

0 comments:

張貼留言