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

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

问题描述

我想使用 HashMap 来缓存依赖于映射中其他条目的昂贵计算.入口模式只提供对匹配值的可变引用,而不提供对 HashMap 其余部分的引用.我非常感谢有关解决此(不正确)玩具示例的更好方法的反馈:

使用 std::collections::HashMap;使用 std::collections::hash_map::Entry::{Occupied, Vacant};fn 计算(缓存:&mut HashMap<u32,u32>,输入:u32)->u32 {匹配缓存.entry(输入){空缺(条目)=>如果输入>2 {//用于昂贵计算的琐碎占位符.*entry.insert(compute(&mut 缓存,输入 - 1) +计算(&mut 缓存,输入 - 2))} 别的 {0},占用(条目)=>*entry.get(),}}fn 主要() {let mut cache = HashMap::<u32, u32>::new();让 foo = 计算(&mut 缓存,12);println!("{}", foo);}

(游乐场)

上述代码段的问题是 cache.entry 不可变地借用了 cache,但我也想更新 cache.

解决方案

首先:您的示例可以使用 .or_insert_with() 方法,该方法采用一个闭包,该闭包返回要在该键处插入的值.p>

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

要真正解决您的问题,您必须分开获取和插入值,如下所示:

fn compute(cache: &mut HashMap, input: u32) ->u32 {if let Some(entry) = cache.get(&input) {返回*条目;}让 res = 如果输入 >2 {//用于昂贵计算的琐碎占位符.计算(缓存,输入 - 1)+ 计算(缓存,输入 - 2)} 别的 {0};缓存.插入(输入,水库);资源}

(如果你在夜间使用 ![feature(nll​​)] 你可以省略 return 并在 elsecode>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);
}

(playground)

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

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