来自HashMap的默认可变值

Tim*_*mmm 9 lifetime rust

假设我有一个HashMap并且我想获得一个条目的可变引用,或者如果该条目不存在我想要一个新对象的可变引用,我该怎么办?我尝试过使用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.
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为它的寿命Vec不够长.有没有办法告诉Rust我希望返回Vec的生命周期与之相同foo()?我的意思是有这个明显的解决方案,但我觉得应该有更好的方法:

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.
}
Run Code Online (Sandbox Code Playgroud)

joc*_*ull 13

正如Shepmaster所提到的,这是一个使用条目模式的例子.起初看起来很冗长,但是这样可以避免分配一个你可能不会使用的数组,除非你需要它.我相信你可以围绕这个做一个通用的功能来减少聊天:)

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");
}
Run Code Online (Sandbox Code Playgroud)

这也可以缩短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");
}
Run Code Online (Sandbox Code Playgroud)

  • 使用[`or_insert`](http://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_insert)是较短的版本([示例](http://是. GD/GQYapJ)). (4认同)

She*_*ter 6

如果你想将你添加dummy到地图中,那么这是如何正确使用HashMap :: entry的副本或者想要使用模式匹配添加到HashMap,一次多次借用可变的(或任何关于entryAPI的问题).

如果您不想添加它,那么您的代码很好,您只需要按照编译器错误消息来修复它.您正在尝试使用关键字作为标识符(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() {}
Run Code Online (Sandbox Code Playgroud)