首页 文章

使用Iterator collect键入问题

提问于
浏览
13

我正在尝试使用以下代码片段将 &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 回答

  • 2

    类型 &(&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() 解决了这个问题,因为它是一个迭代器适配器,如果 T 是可克隆的,它将 Iterator<Item=&T> 转换为 Iterator<Item=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()Vec<T> 获取 Iterator<Item=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);
    }
    
  • 14

    问题是虽然可以复制引用,但元组不能 .

    但是,如果您不再需要对,则可以按值迭代:

    use std::collections::HashMap;
    
    fn main() {
      let pairs = vec!(("foo", "bar"), ("toto", "tata"));
      let map: HashMap<&'static str, &'static str> = pairs.into_iter().collect();
      println!("{:?}", map);
    }
    

相关问题