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

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

问题描述

我想使用 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);}

(playground)

上述代码段的问题在于 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 上使用 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天全站免登陆