簡體   English   中英

Rust 中的 hash 映射在同一 function 中就地修改、插入或刪除

[英]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>應用於vw ,並且:
    • 如果結果為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM