![](/img/trans.png)
[英]How do I create a Rust HashMap where the value can be one of multiple types?
[英]How does one create a HashMap with a default value in Rust?
作為 Rust 的新手,我想知道如何使用鍵的默認值創建HashMap
? 例如,對於HashMap
中插入的任何鍵,都具有默認值0
。
在 Rust 中,我知道這會創建一個空的 HashMap:
let mut mymap: HashMap<char, usize> = HashMap::new();
我希望為一組鍵維護一個計數器,其中一種方法似乎是:
for ch in "AABCCDDD".chars() {
mymap.insert(ch, 0)
}
有沒有辦法在 Rust 中以更好的方式做到這一點,也許相當於 Ruby 提供的東西:
mymap = Hash.new(0)
mymap["b"] = 1
mymap["a"] # 0
回答你遇到的問題...
我希望為一組鍵維護一個計數器。
然后你想看看如何有效地查找並插入 HashMap? . 提示: *map.entry(key).or_insert(0) += 1
回答你問的問題...
如何在 Rust 中創建具有默認值的 HashMap?
不, HashMap
沒有存儲默認值的地方。 這樣做會導致該數據結構的每個用戶都分配空間來存儲它,這將是一種浪費。 您還必須處理沒有適當默認值或無法輕松創建默認值的情況。
相反,您可以使用HashMap::get
查找值,並在缺少時使用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
}
如果unwrap_or
不適用於您的情況,有幾個類似的功能可能:
當然,歡迎您將其包裝在函數或數據結構中以提供更好的 API 。
在 C++ 中,有一個映射的概念,即在訪問鍵時插入默認值。 不過,這似乎總是有點漏:如果類型沒有默認值怎么辦? Rust 對映射類型的要求較低,並且對鍵的存在(或不存在)更為明確。
Rust 對此增加了額外的皺紋。 實際上插入一個值需要簡單地獲取一個值也可以更改HashMap
。 這將使對HashMap
中值的任何現有引用無效,因為可能需要重新分配。 因此,您將不再能夠同時獲得對兩個值的引用! 那將是非常嚴格的。
使用entry
從 HashMap 中獲取一個元素,然后修改它呢?
從文檔:
fn entry(&mut self, key: K) -> Entry<K, V>
獲取地圖中給定鍵的對應條目以進行就地操作。
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);
添加到.entry().or_insert()
的現有示例中,我想提一下,如果傳遞給.or_insert()
的默認值是動態生成的,最好使用.or_insert_with()
。
使用.or_insert_with()
如下,如果鍵已經存在,則不會生成默認值。 它僅在必要時創建。
for v in 0..s.len() {
components.entry(unions.get_root(v))
.or_insert_with(|| vec![]) // vec only created if needed.
.push(v);
}
在下面的片段中,每次調用都會生成傳遞給.or_insert()
的默認向量。 如果密鑰存在,則會創建一個向量,然后將其丟棄,這可能是一種浪費。
components.entry(unions.get_root(v))
.or_insert(vec![]) // vec always created.
.push(v);
因此,對於沒有太多創建開銷的固定值,請使用.or_insert()
,對於具有可觀創建開銷的值,請使用.or_insert_with()
。
使用初始值啟動映射的一種方法是從元組向量構造映射。 例如,考慮下面的代碼:
let map = vec![("field1".to_string(), value1), ("field2".to_string(), value2)].into_iter().collect::<HashMap<_, _>>();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.