繁体   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