HashMap 的默认可变值

Default mutable value from HashMap

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

如果您想将 dummy 添加到地图中,那么这是 or 的副本(或任何关于 entry API 的问题)。

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

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