简体   繁体   English

来自HashMap的默认可变值

[英]Default mutable value from HashMap

Suppose I have a HashMap and I want to get a mutable reference to an entry, or if that entry does not exist I want a mutable reference to a new object, how can I do it? 假设我有一个HashMap ,我想获得一个条目的可变引用,或者如果该条目不存在,我想要一个新对象的可变引用,我该怎么办呢? I've tried using unwrap_or() , something like this: 我尝试过使用unwrap_or() ,如下所示:

fn foo() {
    let mut map: HashMap<&str, Vec<&str>> = HashMap::new();

    let mut ref = map.get_mut("whatever").unwrap_or( &mut Vec::<&str>::new() );

    // Modify ref.
}

But that doesn't work because the lifetime of the Vec isn't long enough. 但这不起作用,因为Vec的寿命不够长。 Is there any way to tell Rust that I want the returned Vec to have the same lifetime as foo() ? 有没有办法告诉Rust我希望返回的Vecfoo()具有相同的生命周期? I mean there is this obvious solution but I feel like there should be a better way: 我的意思是有这个明显的解决方案,但我觉得应该有更好的方法:

fn foo() {
    let mut map: HashMap<&str, Vec<&str>> = HashMap::new();

    let mut dummy: Vec<&str> = Vec::new();
    let mut ref = map.get_mut("whatever").unwrap_or( &dummy );

    // Modify ref.
}

As mentioned by Shepmaster, here is an example of using the entry pattern. 正如Shepmaster所提到的,这是一个使用条目模式的例子。 It seems verbose at first, but this avoids allocating an array you might not use unless you need it. 起初看起来很冗长,但是这样可以避免分配一个你可能不会使用的数组,除非你需要它。 I'm sure you could make a generic function around this to cut down on the chatter :) 我相信你可以围绕这个做一个通用的功能来减少聊天:)

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

fn foo() {
    let mut map = HashMap::<&str, Vec<&str>>::new();
    let mut result = match map.entry("whatever") {
       Vacant(entry) => entry.insert(Vec::new()),
       Occupied(entry) => entry.into_mut(),
    };

    // Do the work
    result.push("One thing");
    result.push("Then another");
}

This can also be shortened to or_insert as I just discovered! 正如我刚刚发现的那样,这也可以简化为or_insert

use std::collections::HashMap;

fn foo() {
    let mut map = HashMap::<&str, Vec<&str>>::new();
    let mut result = map.entry("whatever").or_insert(Vec::new());

    // Do the work
    result.push("One thing");
    result.push("Then another");
}

If you want to add your dummy into the map, then this is a duplicate of How to properly use HashMap::entry? 如果你想将你的dummy添加到地图中,那么这是如何正确使用HashMap :: entry的副本 or Want to add to HashMap using pattern match, get borrow mutable more than once at a time (or any question about the entry API). 或者想要使用模式匹配添加到HashMap,一次多次获取可变多次 (或任何有关entry API的问题)。

If you don't want to add it, then your code is fine, you just need to follow the compiler error messages to fix it. 如果您不想添加它,那么您的代码很好,您只需要按照编译器错误消息来修复它。 You are trying to use a keyword as an identifier ( ref ), and you need to get a mutable reference to dummy ( & mut dummy ): 您正在尝试使用关键字作为标识符( ref ),并且您需要获得对dummy& mut dummy )的可变引用

use std::collections::HashMap;

fn foo() {
    let mut map: HashMap<&str, Vec<&str>> = HashMap::new();

    let mut dummy: Vec<&str> = Vec::new();
    let f = map.get_mut("whatever").unwrap_or( &mut dummy );
}

fn main() {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM