12月 19, 2023 LaGee
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)
稍微講一下有用到的方法
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分連結
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
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:
張貼留言