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 我希望返回的 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.
}
如果您想将 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");
}
假设我有一个 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 我希望返回的 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.
}
如果您想将 dummy
添加到地图中,那么这是 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");
}