我正在尝试使用以下代码段将&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();
但是,如果我在调用.cloned()
之前添加collect()
,一切正常:
...
let map: HashMap<&str, &str> = pairs.iter().cloned().collect();
...
即使我理解错误消息(类型FromIterator<&(&str, &str)>
没有特征HashMap<&str, &str>
的实现),我也不明白类型&(&str, &str)
的来源(根据Rust文档中的方法签名)以及为什么调用cloned()
修复了这个问题。
答案 0 :(得分:15)
&(&str, &str)
类型来自Vec
上的iter()
返回:
fn iter(&self) -> Iter<T>
其中Iter<T>
实现Iterator<Item=&T>
:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T
...
}
换句话说,向量上的iter()
返回一个迭代器,产生对向量的引用。
cloned()
解决了这个问题,因为它是一个迭代器适配器,如果Iterator<Item=&T>
是可克隆的,它会将Iterator<Item=T>
转换为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);
恰好(&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);
}
答案 1 :(得分:2)
问题在于虽然可能会复制引用,但元组却不能。
但是,如果您不再需要配对,则可以按值迭代:
<?php
value = id;
//codings
?>