问题描述
我想使用 HashMap
来缓存依赖于地图中其他条目的昂贵计算.条目模式仅提供对匹配值的可变引用,而不提供对 HashMap
其余部分的可变引用.我非常感谢有关解决此(不正确)玩具示例的更好方法的反馈:
使用 std::collections::HashMap;使用 std::collections::hash_map::Entry::{Occupied, Vacant};fn计算(缓存:&mut HashMap<u32,u32>,输入:u32)->u32 {匹配 cache.entry(输入){空缺(条目)=>如果输入 >2 {//昂贵计算的琐碎占位符.*entry.insert(compute(&mut cache, input - 1) +计算(&mut 缓存,输入 - 2))} 别的 {0},占用(条目)=>*entry.get(),}}fn 主(){让 mut cache = HashMap::::new();让 foo = 计算(&mut 缓存,12);println!("{}", foo);}
上述代码段的问题在于 cache.entry
不可变地借用了 cache
,但我也想更新 cache
.
首先:您的示例可以使用 .or_insert_with()
方法,该方法采用闭包,该闭包返回要插入该键的值.>
条目模式不可能解决您的问题,因为您首先在条目中可变地借用缓存,然后在匹配(或闭包)中借用缓存.您可以尝试一下,如果您使用 RefCell
(它只是将借用从编译时移动到运行时),它会引发恐慌.
要真正解决您的问题,您必须拆分获取和插入值,如下所示:
fn compute(cache: &mut HashMap, input: u32) ->u32 {if let Some(entry) = cache.get(&input) {返回*条目;}让 res = if input >2 {//昂贵计算的琐碎占位符.计算(缓存,输入 - 1)+ 计算(缓存,输入 - 2)} 别的 {0};缓存.插入(输入,资源);资源}
(如果您在夜间使用 ![feature(nll)]
,您可以省略 return
并在 else
上使用 else
code>if let 分支使其更简洁.
I'd like to use a HashMap
to cache an expensive computation that's dependent on other entries in the map. The entry pattern only provides a mutable reference to the matched value, but not to the rest of the HashMap
. I'd really appreciate feedback on a better way to solve this (incorrect) toy example:
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
fn compute(cache: &mut HashMap<u32, u32>, input: u32) -> u32 {
match cache.entry(input) {
Vacant(entry) => if input > 2 {
// Trivial placeholder for an expensive computation.
*entry.insert(compute(&mut cache, input - 1) +
compute(&mut cache, input - 2))
} else {
0
},
Occupied(entry) => *entry.get(),
}
}
fn main() {
let mut cache = HashMap::<u32, u32>::new();
let foo = compute(&mut cache, 12);
println!("{}", foo);
}
The issue with the above snippet is that cache.entry
borrows cache
immutably, but I would like to update cache
as well.
First things first: your example can be simplified with the .or_insert_with()
method that takes a closure which returns the value to insert at that key.
It is not possible with the entry pattern to solve your problem, because you mutably borrow the cache first in your entry, and afterwards in your match (or closure). You can try it, if you use a RefCell
(which just moves the borrowing from compiletime to runtime) it will throw a panic.
To actually solve your problem, you have to split getting and inserting the value, like this:
fn compute(cache: &mut HashMap<u32, u32>, input: u32) -> u32 {
if let Some(entry) = cache.get(&input) {
return *entry;
}
let res = if input > 2 {
// Trivial placeholder for an expensive computation.
compute(cache, input - 1) + compute(cache, input - 2)
} else {
0
};
cache.insert(input, res);
res
}
(if you are on nightly and using ![feature(nll)]
you can omit the return
and use else
on the if let
branch to make it a little bit cleaner.
这篇关于使用条目模式时如何改变 HashMap 的其他元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!