我有一个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天代码的出现。
使用copied
或cloned
将Option<&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);
不用说,只有当你可以通过修改地图时,这才有效