[英]In-place modification, insertion or removal in the same function for hash maps in Rust
假設我有一個 hash map m: HashMap<K, V>
,一個鍵k: K
和一個值v: V
,並且想做以下事情:
m
在索引k
處不包含值,則在索引k
處插入v
。m
在索引k
處包含值w
,則將 function fn combine(x: V, y: V) -> Option<V>
應用於v
和w
,並且:
None
,則從m
中刪除索引k
處的條目。Some(u)
,將索引k
處的值替換為u
。 有沒有辦法“就地”執行此操作,而無需調用多次訪問、修改或刪除k
處的值的函數?
我還想避免復制數據,所以理想情況下不需要克隆v
來將克隆提供給insert
並單獨combine
。
我可以重寫combine
以使用(可變)引用(或內聯它),但不復制數據的願望仍然存在。
深入研究Entry
文檔,我注意到Entry
枚舉的變體提供了就地修改、刪除或插入條目的功能。
在采取std::collections::hash_map::Entry
進入 scope 之后,可以執行以下操作:
match m.entry(k) {
Entry::Occupied(mut oe) => {
let w = oe.get_mut();
match combine(v, w) {
Some(u) => { *w = u; },
None => { oe.remove_entry(); },
}
},
Entry::Vacant(ve) => { ve.insert(v); },
}
( 這是 Rust 操場上的 PoC。)
但是,這需要combine
將(可變)引用作為其第二個參數(在我的情況下這很好)。
在最壞的情況下,我設法通過一次訪問、一次寫入和一次刪除密鑰來完成。 最后一個鍵刪除應該不是必需的,但我不確定它是否可以完成。 到目前為止,我已經盡力了。 我希望這有幫助!
好的,所以我想我們想使用條目 API 。
Entry
的完整方法列表在這里。
我想我們會按照以下順序進行:
m
在索引k
處包含值w
:(再執行兩步)k
處插入v
。 這可以通過使用.and_modify
然后.or_insert
來完成。 像這樣的東西:
let map = // ... Initialize the map
// Do stuff to it
// ...
// Our important bit:
let mut delete_entry = false;
map.entry(k)
.and_modify(|w| { // If the entry exists, we modify it
let u = combine(v, w);
match u {
Some(y) => *w = y;
None => delete_entry = true;
}
}
)
.or_insert(v); // If it doesn't, we insert v
if delete_entry {
map.remove(k);
}
如果沒有最后一個map.remove
訪問權限,我認為沒有辦法完成所有三件事,所以這是我目前最好的嘗試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.