我正在尝试使用以下代码片段将对矢量转换&str为a HashMap:
use std::collections::HashMap;
fn main() {
let pairs = vec!(("foo", "bar"), ("toto", "tata"));
let map: HashMap<&str, &str> = pairs.iter().collect();
println!("{:?}", map);
}
Run Code Online (Sandbox Code Playgroud)
但是编译失败并出现此错误:
<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();
Run Code Online (Sandbox Code Playgroud)
但是,如果我.cloned()在调用之前添加collect()一切正常:
...
let map: HashMap<&str, &str> = pairs.iter().cloned().collect();
...
Run Code Online (Sandbox Code Playgroud)
即使我理解错误消息(没有FromIterator<&(&str, &str)>该类型的特征的实现HashMap<&str, &str>)我不明白类型&(&str, &str)来自哪里(根据Rust文档中的方法签名)以及为什么调用cloned()修复这个问题.
Vla*_*eev 21
该类型&(&str, &str)来自哪iter()一个Vec回报:
fn iter(&self) -> Iter<T>
Run Code Online (Sandbox Code Playgroud)
在哪里Iter<T>实现Iterator<Item=&T>:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T
...
}
Run Code Online (Sandbox Code Playgroud)
换句话说,iter()在向量上返回一个迭代器,产生对向量的引用.
cloned()解决了这个问题,因为它是一个迭代器适配器,转换Iterator<Item=&T>为Iterator<Item=T>if T是可克隆的.您可以将其视为以下的简写map(|v| v.clone()):
let v1: Vec<i32> = vec![1, 2, 3, 4];
let v2: Vec<_> = v1.iter().cloned().collect();
let v3: Vec<_> = v1.iter().map(|v| v.clone()).collect();
assert_eq!(v2, v3);
Run Code Online (Sandbox Code Playgroud)
它(&str, &str)是可克隆的,因为每个元组组件也是可克隆的(所有引用都是),因此cloned()会返回一个实现的对象Iterator<Item=(&str, &str)>- 确切地说collect()需要创建一个HashMap.
或者,你可以用into_iter()得到Iterator<Item=T>的Vec<T>,但随后的原始载体将被消耗:
use std::collections::HashMap;
fn main() {
let pairs = vec!(("foo", "bar"), ("toto", "tata"));
let map: HashMap<&str, &str> = pairs.into_iter().collect();
println!("{:?}", map);
}
Run Code Online (Sandbox Code Playgroud)