从HashMap中获取实数或None



我有一个struct,我想基于一个可能不完整的哈希图来填充它:

#[derive(Debug)]
struct Sue {
children: Option<u8>,
cats: Option<u8>,
samoyeds: Option<u8>,
pomeranians: Option<u8>,
akitas: Option<u8>,
vizslas: Option<u8>,
goldfish: Option<u8>,
trees: Option<u8>,
cars: Option<u8>,
perfumes: Option<u8>,
}
impl Sue {
fn from_line(line: &str) -> Sue {
let data: Vec<&str> = line.split(" ").collect();
let items: HashMap<String, u8> = data[2..data.len()]
.chunks(2)
.map(|item| {
(
String::from(item[0].trim_end_matches(":")),
String::from(item[1].trim_end_matches(",")).parse().unwrap(),
)
})
.collect();
println!("{:?}n", items);
Sue {
// children: match items.get("children"){
// Some(val) => Some(*val),
// None => None,
// },
children: *items.get("children"),
// cats: Some(0),
// samoyeds: Some(0),
// pomeranians: Some(0),
// akitas: Some(0),
// vizslas: Some(0),
// goldfish: Some(0),
// trees: Some(0),
// cars: Some(0),
// perfumes: Some(0),
}
}
}

在上面的摘录中,items散列映射可以包含也可以不包含用于Sue结构的每个字段的键。我的想法是用输入构建一个哈希映射,然后对于结构的每个字段,尝试访问哈希映射的相应键。如果键在hashmap中,则返回取消引用的值。如果密钥不在hashmap中,则返回None。

我知道我可以用一场比赛来做到这一点(有几行评论显示了我将如何做到这一步(,但我想知道是否有更有效的方法来做到这(这是很多样板;每个场地一场比赛(。

如果我运行上面的代码,我会得到:

error[E0614]: type `Option<&u8>` cannot be dereferenced

知道吗?如果找不到钥匙,我确实想保留"无"。同样为了参考,这个片段是为2015年第16天代码的出现。

使用copiedclonedOption<&T>转换为Option<T>。如果T: Copy,则第一个可用,如果T: Clone,则第二个可用。

u8实现了这两种方法,因此您可以使用其中一种方法。

children: items.get("children").copied(),

对于u8,John Kugelman提到的任何一种方法都非常有效。然而,有些类型既不能实现Copy,也不能廉价地克隆(也许它们根本没有实现Clone,或者它们实现了,但成本很高(。

第三种选择是从地图上删除该项目:


struct ExpensiveClone(u8);
impl Clone for ExpensiveClone {
fn clone(&self) -> Self {
std::thread::sleep(Duration::from_secs(1));
Self(self.0)
}
}

在这种情况下,克隆的成本可能高得令人望而却步。相反,如果您拥有对映射的所有权或可变访问权限,则可以删除它,将值的所有权从映射转移到您的函数,而无需克隆数据:

let mut map = HashMap::new();
map.insert(1, ExpensiveClone(1));
let expensive_clone = map.remove(&1).unwrap();
assert_eq!(expensive_clone.0, 1);

不用说,只有当你可以通过修改地图时,这才有效

最新更新