使用进入模式时,如何更改HashMap的其他元素? [英] How can I mutate other elements of a HashMap when using the entry pattern?

查看:82
本文介绍了使用进入模式时,如何更改HashMap的其他元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 HashMap 缓存依赖于地图中其他条目的昂贵计算。进入模式仅提供对匹配值的可变引用,而没有提供对 HashMap 其余部分的引用。我真的很感谢您提供反馈来解决这个(错误)玩具示例的更好方法:

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);
}

操场

问题在于上面的代码片段是 cache.entry 不变地借用了 cache ,但是我想更新缓存

The issue with the above snippet is that cache.entry borrows cache immutably, but I would like to update cache as well.

推荐答案

第一件事:使用 .or_insert_with() 方法带有一个闭包,该闭包返回要在该键处插入的值。

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.

输入模式无法解决您的问题,因为您是可变地首先在条目中借用了缓存,然后在匹配(或关闭)中借用了缓存。您可以尝试一下,如果使用 RefCell (它将借用从编译时移至运行时),则会引发恐慌。

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
}

(如果您在夜间使用![feature(nll)] ,您可以省略返回并使用 else if let 分支上,使其更加整洁。

(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的其他元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆