and_modify() 与 or_insert()
在 Rust 下有两个map:BTreeMap 与 HashMap。
我们日常在使用 map 的时候经常会遇到这样的情景:
let mut map = HashMap::new();// ...map[&key] += val;
在 C++、Python 等等支持 map 结构的语言中,这样子的操作不会遇到任何问题,但是在Rust 中,这样的操作会有以下问题:
key不一定存在在map中。Rust会对每个[]操作做越界检查,因此map[&key]其实是相当于C++中的map.at(key)map[&key]得到的是一个immutable的引用,不可以直接加上一个val
在之前,我一般使用这样的方式来解决这个问题:
if let Some(e) = map.get_mut(&key) {*e += val;} else {map.insert(key, val);}
这么写也能解决问题,但是很长,而且绕了几个弯子,很难一眼看出代码的意图。
在参考了 这个提问 后,我发现了几个好用的“彩蛋”:and_modify() 与 or_insert()。
之所以说是彩蛋,是因为它藏得太隐蔽了。。。我在之前使用
clippy处理我的代码的时候从未遇到过有关于此的提示。Rust 总是会有这样子的现象,你以为它缺少某个功能而不方便使用,但是其实它就在那里,得靠你自己去发现,然后它会告诉你,看,不是我不好用,只是你笨。Orz
这两个函数很好地解决了以上的问题:
map.entry(&key).and_modify(|e| *e += val).or_insert(val)
此外还有几个类似的函数:
or_default,只对实现了Default trait的值有用or_insert_with,和or_insert的区别是:or_insert插入一个值,而or_insert_with插入的是一个函数的返回值or_insert_with_kay,在or_insert_with的基础上,将key作为函数的参数传入
