Rust: HashMap的用法及其它

和其它语言的Dict,dict,Dictionary等不太一样,Rust的HashMap很独特。

let mut contacts = HashMap::new();

contacts.insert("Daniel", "798-1364");
contacts.insert("Ashley", "645-7689");
contacts.insert("Katie", "435-8291");
contacts.insert("Robert", "956-1745");

let temp = contacts.get("Daniel");
assert_eq!(Some(&"798-1364"), temp); // 注意:& ,不是 Some("798-1364")!

let temp2 = contacts.get(&"Daniel");
assert_eq!(Some(&"798-1364"), temp2); //注意:& ,不是 Some("798-1364")!

为了有代表性,设计了一个相对复杂的双层HashMap+内置Vec的结构,如果还不够有代表性,那就没办法了,具体如下:

HashMap<&str, HashMap<&str, Boxf32>>>>

一、insert

   let mut hd: HashMap<&str, HashMap<&str, Boxf32>>>> = HashMap::new();
   let mut tm1 = HashMap::new();
//方法一: 如果tm1没有“book1”key,则insert key为“book1”和相应元素值。
   tm1.entry("book1").or_insert(Box::new(vec![1.0_f32]));
   hd.insert("rust", tm1);
   println!("insert rust hd=>{:?}", hd);

//方法二: 直接insert
   let mut tm2 = HashMap::new();
   tm2.insert("book1", Box::new(vec![2.0_f32]));
   hd.insert("julia", tm2);

   println!("insert julia hd=>{:?}", hd);

// insert: Rust允许相同key的重复操作,会进行覆盖操作。

    let mut tm3 = HashMap::new();
    tm3.insert("book1", Box::new(vec![2.0_f32]));
    hd.insert("julia", tm3);

总体上,虽然操作上不如一些脚本语言一样简洁,但还算中规中矩。

二、remove

hd.remove("julia"); //删除"julia"对应的key-value对。

三、对vec内部元素的类似push的操作

对于上述hd变量,若要对其中的Vec的元素进行增加操作,是否和python,或其它语言一样?

可惜:Rust没有

hd["rust"]["book1"].push(3.0_f32);// error!

虽然,hd有以下的取值的方式:

&hd2["rust"]["book1"]

但是,

&hd2["rust"]["book1"].push(3.0_f32) //error!

如何办?

嘿嘿,get_mut(),醒醒,说你呢,该轮到你上场了。

(1)上面的类型


对于HashMap<&str, HashMap<&str, Box>>>类型,要对最里面进行增加元素操作:

hd.get_mut("rust").unwrap().get_mut("book1").unwrap().push(3.0_f32);
println!("addvalue =>hd:{:?}", hd);//可以看到,Vec元素增加了!

(2)HashMap<&str, Vec>类型


比如,对于HashMap<&str, Vec<f32>>类型,要对最里面Vec<f32>进行增加元素的操作(假设里面有“rust”key),可以:

hd.get_mut("rust").unwrap().push(3.0_f32);

四、HashMap的key,value值

1、总体的keys,values:

let keys = hd.keys();
println!("keys:{:?}", keys); // ["rust","julia"]
let values = hd.values(); 
println!("values :{:?}", values);

注意,有hd.values_mut(),但没有keys_mut(),具体使用法,可以查阅Rust官网。

2、某个key对应的值

let value_key = hd.get("rust").unwrap().clone();
println!("value_key :{:?}", value_key);

或 ,注意下面&

let value_key2 =&hd["rust"]["book1"] // =>[1,2]

3、判断某个key是否在

let bool_key = hd.contains_key("rust");
println!("bool_key :{:?}", bool_key);//true

五、HashMap循还

    for key in hd.keys() {
        println!("key:{:?}", key);
    }
    for (key, value) in &hd {
        println!("key:{:?} value :{:?}", key, value);
    }
    for (key, value) in hd.iter() {
        println!("=>key:{:?} value :{:?}", key, value);
    }

let mut mp = HashMap::new();
mp.insert("a", 1);
mp.insert("b", 2);
mp.insert("c", 3);

//iter_mut()
for (_, val) in mp.iter_mut() {
    *val *= 2;
}

//注意没有keys_mut()
for val in mp.values_mut() {
    *val = *val + 10;
}

六、HashMap <=>Vec

1、HashMap =>Vec

    let vec: Vec<(_, _)> = hd.into_iter().collect();

    println!("vec :{:?}", vec);

2、Vec=>HashMap
(1) Vec<(&str,i32)>

let timber_resources: HashMap<&str, i32> =
    [("Norway", 100),
     ("Denmark", 50),
     ("Iceland", 10)]
     .iter().cloned().collect();

(2) Vec

let data =vec![1,2,3,4,5];
let mut mp2: HashMap = data.iter().map(|&x| (x, x * 10)).collect();

(3)双Vec=>HashMap

let names = vec!["WaySLOG", "Mike", "Elton"];
let scores = vec![60, 80, 100];
let score_map: HashMap<_, _> = names.iter()
.zip(scores.iter())
.collect();
println!("{:?}", score_map);

比如,我们有两个&str,如何变成HashMap

struct Cipher {
    hp: HashMap,
}

impl Cipher {
    fn new(map1: &str, map2: &str) -> Cipher {
        let map = map1.chars()
            .map(|x| x.to_string())
            .zip(map2.chars().map(|y| y.to_string()))
            .collect::>();
        Cipher { hp: map }
    }
 }

七、HashMap =>range

1、range =>HashMap

let mut mp: HashMap<i64, i64> = (0..8).map(|x|(x, x*10)).collect();
mp.retain(|&k, _| k % 2 == 0);
assert_eq!(mp.len(), 4);
let data: HashMap<char, i32> =
        "abcdefghijklmnopqrstuvwxyz".chars().enumerate().map(|(x, y)| (y, x as i32 + 1)).collect();

注意:暂时还没找到‘a’..’z’这种Range的简便方法,其它的好办!

//以下是错误的!!!!!!!!!!!
let data: HashMap = ('a'..'z').chars().enumerate().map(|(x, y)| (y, x as i32 + 1)).collect();

2、 HashMap=>Vec

    let mut v: Vec<i64> = mp.iter().map(|(_, &val)| val).collect();
    println!("v:{:?}", v);

八、keys

    let mut contacts = HashMap::new();
    contacts.insert("Daniel", "798-1364");
    contacts.insert("Ashley", "645-7689");
    contacts.insert("Katie", "435-8291");
    contacts.insert("Robert", "956-1745");
    let names: Vec<&str> = contacts.keys().into_iter().map(|&x| x).collect();
    let nums: Vec<&str> = contacts.values().into_iter().map(|&x| x).collect();

注意,上面不能用iter(),只能用into_inter().

九、为什么 Rust 的 HashMap 很慢?

“默认情况下,Rust 的 HashMap 使用 SipHash 哈希算法,其旨在防止哈希表碰撞攻击,同时在各种工作负载上提供合理的性能。
虽然 SipHash 在许多情况下表现出竞争优势,但其中一个比其它哈希算法要慢的情况是使用短键,例如整数。这就是为什么 Rust 程序员经常观察到 HashMap 表现不佳的原因。在这些情况下,经常推荐 FNV 哈希,但请注意,它不具备与 SipHash 相同的防碰撞性。”

特此说明:此部分见:https://www.rust-lang.org/zh-CN/faq.html

关于HashMap的应用实证和优化,希望有机会做些尝试,毕竟这个关键性的数据结构,特别是量化研究。

十、其它常用的函数

1、is_empty()
2、len();
3、reserve()
4、drain();
5、capacity()
6、hasher()
7、with_capacity_and_hasher()
8、with_hasher()
9、shrink_to_fit()
10、entry()
11、clear()

你可能感兴趣的:(Rust)