我正在尝试使用以下代码片段将 &str
对的向量转换为 HashMap
:
use std::collections::HashMap;
fn main() {
let pairs = vec!(("foo", "bar"), ("toto", "tata"));
let map: HashMap<&str, &str> = pairs.iter().collect();
println!("{:?}", map);
}
但是编译失败并出现此错误:
<anon>:5:47: 5:56 error: the trait `core::iter::FromIterator<&(&str, &str)>` is not implemented for the type `std::collections::hash::map::HashMap<&str, &str>` [E0277]
<anon>:5 let map: HashMap<&str, &str> = pairs.iter().collect();
但是,如果我在调用 collect()
之前添加 .cloned()
一切正常:
...
let map: HashMap<&str, &str> = pairs.iter().cloned().collect();
...
即使我理解错误消息(没有 HashMap<&str, &str>
类型的特性 FromIterator<&(&str, &str)>
的实现)我不明白 &(&str, &str)
类型的来源(根据Rust文档中的方法签名)以及为什么调用 cloned()
修复了这个问题 .
2 回答
类型
&(&str, &str)
来自Vec
上的iter()返回:其中Iter<T>实现
Iterator<Item=&T>
:换句话说,向量上的
iter()
返回一个迭代器,产生对向量的引用 .cloned()
解决了这个问题,因为它是一个迭代器适配器,如果T
是可克隆的,它将Iterator<Item=&T>
转换为Iterator<Item=T>
. 您可以将其视为map(|v| v.clone())
的简写:碰巧
(&str, &str)
是可复制的,因为每个元组组件也是可复制的(所有引用都是),因此cloned()
将返回一个实现Iterator<Item=(&str, &str)>
的对象 - 正是collect()
需要创建HashMap
.或者,您可以使用
into_iter()
从Vec<T>
获取Iterator<Item=T>
,但随后将使用原始矢量:问题是虽然可以复制引用,但元组不能 .
但是,如果您不再需要对,则可以按值迭代: