How does one create a HashMap with a default value in Rust?

前端 未结 2 1449
死守一世寂寞
死守一世寂寞 2020-12-17 16:17

Being fairly new to Rust, I was wondering on how to create a HashMap with a default value for a key? For example, having a default value 0 for any

相关标签:
2条回答
  • 2020-12-17 16:26

    What about using entry to get an element from the HashMap, and then modify it.

    From the docs:

    fn entry(&mut self, key: K) -> Entry<K, V>
    

    Gets the given key's corresponding entry in the map for in-place manipulation.

    example

    use std::collections::HashMap;
    
    let mut letters = HashMap::new();
    
    for ch in "a short treatise on fungi".chars() {
        let counter = letters.entry(ch).or_insert(0);
        *counter += 1;
    }
    
    assert_eq!(letters[&'s'], 2);
    assert_eq!(letters[&'t'], 3);
    assert_eq!(letters[&'u'], 1);
    assert_eq!(letters.get(&'y'), None);
    
    0 讨论(0)
  • 2020-12-17 16:42

    Answering the problem you have...

    I am looking to maintain a counter for a set of keys.

    Then you want to look at How to lookup from and insert into a HashMap efficiently?. Hint: *map.entry(key).or_insert(0) += 1


    Answering the question you asked...

    How does one create a HashMap with a default value in Rust?

    No, HashMaps do not have a place to store a default. Doing so would cause every user of that data structure to allocate space to store it, which would be a waste. You'd also have to handle the case where there is no appropriate default, or when a default cannot be easily created.

    Instead, you can look up a value using HashMap::get and provide a default if it's missing using Option::unwrap_or:

    use std::collections::HashMap;
    
    fn main() {
        let mut map: HashMap<char, usize> = HashMap::new();
        map.insert('a', 42);
    
        let a = map.get(&'a').cloned().unwrap_or(0);
        let b = map.get(&'b').cloned().unwrap_or(0);
    
        println!("{}, {}", a, b); // 42, 0
    }
    

    If unwrap_or doesn't work for your case, there are several similar functions that might:

    • Option::unwrap_or_else
    • Option::map_or
    • Option::map_or_else

    Of course, you are welcome to wrap this in a function or a data structure to provide a nicer API.


    ArtemGr brings up an interesting point:

    in C++ there's a notion of a map inserting a default value when a key is accessed. That always seemed a bit leaky though: what if the type doesn't have a default? Rust is less demanding on the mapped types and more explicit about the presence (or absence) of a key.

    Rust adds an additional wrinkle to this. Actually inserting a value would require that simply getting a value can also change the HashMap. This would invalidate any existing references to values in the HashMap, as a reallocation might be required. Thus you'd no longer be able to get references to two values at the same time! That would be very restrictive.

    0 讨论(0)
提交回复
热议问题