来自HashMap的默认可变值

时间:2015-06-30 14:40:18

标签: rust lifetime

假设我有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.
}

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

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.
}

2 个答案:

答案 0 :(得分:12)

正如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");
}

我刚刚发现,这也可以缩短为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");
}

答案 1 :(得分:6)

如果您要将dummy添加到地图中,则会与How to properly use HashMap::entry?Want to add to HashMap using pattern match, get borrow mutable more than once at a time(或有关entry API的任何问题)重复。< / p>

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