假设我有这些结构体:
struct Data {
url: String,
timestamp: u32
}
struct AuthorAndData {
url: String,
timestamp: u32,
author: String
}
我想把Data
的向量转换成一个哈希Map,其中AuthorAndData
是值。
基本上是这样的:
let input: Vec<(Result<Data, String>, String)> = vec![(Ok(Data {
url: "http://google.com".to_string(),
timestamp: 1234566,
}), "john".to_string()), (Ok(Data {
url: "http://yahoo.com".to_string(),
timestamp: 2333333,
}), "doe".to_string()), (Ok(Data {
url: "http://google.com".to_string(),
timestamp: 2333353,
}), "doe".to_string())];
我想把它转换成一个哈希Map,其中URL是键,值是AuthorAndData
的vec。
基本上从Vec<(Result<Data, String>, String)>
到HashMap<String, Vec<AuthorAndData>>
我的第一个尝试是这样的:
let mut mappped: HashMap<String, Vec<AuthorAndData>> = HashMap::new();
input.iter().for_each(|entry| {
mappped.entry(entry.0.unwrap().url).and_modify(|value| value.push(AuthorAndData {
url: entry.0.unwrap().url,
timestamp: entry.0.unwrap().timestamp,
author: entry.1
})).or_insert(vec![AuthorAndData {
url: entry.0.unwrap().url,
timestamp: entry.0.unwrap().timestamp,
author: entry.1
}]);
});
但编译失败,出现错误:
error[E0507]: cannot move out of `entry.0` which is behind a shared reference
--> src/main.rs:60:18
|
60 | url: entry.0.unwrap().url,
| ^^^^^^^ -------- `entry.0` moved due to this method call
| |
| help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
| move occurs because `entry.0` has type `Result<Data, std::string::String>`, which does not implement the `Copy` trait
|
在通过添加.as_ref()
修复这些错误后,我又遇到了一些与添加clone()
有关的错误。
let mut mappped: HashMap<String, Vec<AuthorAndData>> = HashMap::new();
input.iter().for_each(|entry| {
mappped.entry(entry.0.as_ref().unwrap().url).and_modify(|value| value.push(AuthorAndData {
url: entry.0.as_ref().unwrap().url,
timestamp: entry.0.unwrap().timestamp,
author: entry.1
})).or_insert(vec![AuthorAndData {
url: entry.0.unwrap().url,
timestamp: entry.0.unwrap().timestamp,
author: entry.1
}]);
});
失败
error[E0507]: cannot move out of a shared reference
--> src/main.rs:60:18
|
60 | url: entry.0.as_ref().unwrap().url,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `std::string::String`, which does not implement the `Copy` trait
但是附加具有作为entry.0.as_ref().unwrap().url.clone()
的行的clone()
IE固定了它。
我想要的最终版本如下所示:
fn main() {
#[derive(Debug)]
struct Data {
url: String,
timestamp: u32
}
#[derive(Debug)]
struct AuthorAndData {
url: String,
timestamp: u32,
author: String
}
let input: Vec<(Result<Data, String>, String)> = vec![(Ok(Data {
url: "http://google.com".to_string(),
timestamp: 1234566,
}), "john".to_string()), (Ok(Data {
url: "http://yahoo.com".to_string(),
timestamp: 2333333,
}), "doe".to_string()), (Ok(Data {
url: "http://google.com".to_string(),
timestamp: 2333353,
}), "doe".to_string())];
let mut mappped: HashMap<String, Vec<AuthorAndData>> = HashMap::new();
input.iter().for_each(|entry| {
mappped.entry(entry.0.as_ref().unwrap().url.clone()).and_modify(|value| value.push(AuthorAndData {
url: entry.0.as_ref().unwrap().url.clone(),
timestamp: entry.0.as_ref().unwrap().timestamp.clone(),
author: entry.1.clone()
})).or_insert(vec![AuthorAndData {
url: entry.0.as_ref().unwrap().url.clone(),
timestamp: entry.0.as_ref().unwrap().timestamp.clone(),
author: entry.1.clone()
}]);
});
dbg!(mappped);
}
运行这个打印正确的结果,但我怀疑这是否是最好的方法给所有的as_ref
和clone
,我不得不洒在整个地方得到这个工作。
任何人都知道:
1.为什么需要所有as_ref
和clone
1.更好的方法是不需要所有这些as_ref
和clone
1条答案
按热度按时间zbwhf8kr1#
1.为什么需要所有
as_ref
和clone
因为只有来自
iter()
的共享引用,所以不能移出它。unwrap()
移出Option
,所以需要as_ref()
。移动字段也是不可能的,所以需要clone()
。1.更好的方法是不需要所有这些
as_ref
和clone
如果要将
iter()
更改为into_iter()
,可以更改or_insert()
以移动值(此外,首选or_insert_with()
,以便在条目已满时不分配向量):如果你将
and_modify().or_insert()
进一步修改为match
,向借位检查器证明只有一个分支可以执行,你可以避免在两个分支中进行克隆:更好的是,您可以在修改现有条目之前使用
or_insert()
,从而大大简化代码: