12月 21, 2023 LaGee
HashMap4
前面打了三篇心得
Rust HashMap概述1 - key與value集合 ~ LaGee-Blog (lageeblog.blogspot.com)
Rust HashMap概述2 - get、get_key_value、雙重HashMap ~ LaGee-Blog (lageeblog.blogspot.com)
Rust HashMap概述3 - 刪除資料clear、drain、remove、retain ~ LaGee-Blog (lageeblog.blogspot.com)
這篇第四篇
主要講述RustMap如何跟迭代運用
會使用到map和for迴圈
以及數組和HashMap互相轉換
最後會示範一下如何用把HashMap裡面的東西照著value排序
迭代
pub fn iter(&self) -> Iter<'_, K, V>
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> ⓘ
HashMap也是可以迭代
有兩種方式
一種是iter、一種是iter_mut
回傳key和value
iter_mut可以直接對迭代器中數值更改
假設我是一個佛心老師
想要把成績都開根號乘以10
可以這樣子
use std::collections::HashMap;
fn main() {
let score_map: HashMap<&str, u8> = HashMap::from([
("Chinese", 64),
("Math", 81),
("English", 36),
]);
let map_iter: HashMap<&str, u8> = score_map
.iter()
.map(|(k, v)| (*k, ((*v as f64).sqrt() * 10.0) as u8))
.collect();
println!("before bonus score: {:?}", score_map);
println!("after bonus score: {:?}", map_iter);
}
before bonus score: {"Chinese": 64, "Math": 81, "English": 36}
after bonus score: {"Chinese": 80, "Math": 90, "English": 60} 先透過iter將score_map放入迭代器中
使用map[3],閉包內需要輸入兩個值
因為最後collect是回傳key和value,因此map裡面也需要回傳兩個值
這題不對key做處理,只對value做處理
因此value轉f64,開根號sqrt後再乘以10,並且轉成u8以符合型態
最後輸出可以看到所有數值都開根號乘10了
而都使用iter了當然也可以使用for迴圈
let score_map: HashMap<&str, u8> = HashMap::from([
("Chinese", 64),
("Math", 81),
("English", 36),
]);
for (k,v) in score_map {
println!("{}, after bonus score: {}", k, (v as f64).sqrt() * 10.0);
}
Chinese, after bonus score: 80
Math, after bonus score: 90
English, after bonus score: 60
for的前面要放兩組變數
分別代表key和value
如果想要直接修改HashMap的值可以使用iter_mut
let mut score_map: HashMap<&str, u8> = HashMap::from([
("Chinese", 64),
("Math", 81),
("English", 36),
]);
for (_,v) in score_map.iter_mut() {
*v = ((*v as f64).sqrt() * 10.0) as u8;
}
println!("after bouns score: {:?}", score_map);
after bouns score: {"Math": 90, "English": 60, "Chinese": 80}
要對其解引用
之後可以直接更改HashMap裡面的值
數組、HashMap轉換
數組和HashMap是可以互相轉換的
數組轉HashMap
use std::collections::HashMap;
fn main() {
let score_vec = vec![("Chinese", 64), ("Math", 81), ("English", 36)];
let score_map = score_vec.into_iter().collect::<HashMap<_,_>>();
// println!("{:?}", score_vec); panic
println!("{:?}", score_map);
}
{"English": 36, "Math": 81, "Chinese": 64}數組內需要有一個由元組組成的數組
元組內兩個值,代表K和V
要注意數組轉HashMap是要所有權的
如果是用引用iter(),會發生panic
因此要使用iter_mut把所有權轉給迭代器,之後collect
輸出結果會把前面那個科目當作K,後面數字當作V
HashMap轉數組
use std::collections::HashMap;
fn main() {
let score_map: HashMap<&str, u8> =
HashMap::from([("Chinese", 64), ("Math", 81), ("English", 36)]);
let score_vec: Vec<(&str, u8)> = score_map.into_iter().collect::<Vec<_>>();
// println!("map: {:?}", score_map); panic
println!("vec: {:?}", score_vec);
}
vec: [("Chinese", 64), ("Math", 81), ("English", 36)]HashMap轉數組一樣
使用into_iter轉移所有權
如果沒轉移所有權只會拿到引用值
轉移後數組裡面一樣是元組
根據value排序
HashMap是一個無序的集合
意思是我不能保證每次輸出的順序都一樣
假設我希望把順序依照value排序
需要轉vec後使用sort_by或sort_by_key排序
use std::collections::HashMap;
fn main() {
let score_map: HashMap<&str, u8> =
HashMap::from([("Chinese", 64), ("Math", 81), ("English", 36)]);
println!("before sort: {:?}", score_map);
let mut score_vec = score_map.iter().collect::<Vec<_>>();
score_vec.sort_by_key(|(_, &v)| v);
println!("after sort: {:?}", score_vec);
}
before sort: {"Math": 81, "English": 36, "Chinese": 64}
after sort: [("English", 36), ("Chinese", 64), ("Math", 81)]這邊使用sort_by_key[4]排序
轉成vec後
使用sort_by_key根據value
輸出後可看到有排序
如果需要轉回HashMap可以用上面的方法轉
參考資料
[1] https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.iter
[2] https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.iter_mut
[3] https://lageeblog.blogspot.com/2023/10/rust-map.html
[4] https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by_key
0 comments:
張貼留言