Rust 从迭代器中收集 HashMap

标签 rust hashmap iterator tuples

我们有一个 HashMap,我们对其进行迭代和映射以替换值,但是遇到了一个问题,将其收集回具有不同值类型的新 HashMap。

value of type `std::collections::HashMap<std::string::String, std::string::String>`
cannot be built from `std::iter::Iterator<Item=(&std::string::String, std::string::String)>`
我们所做的基本上归结为:
let old: HashMap<String, Value> = some_origin();
let new: HashMap<String, String> = old.iter().map(|(key, value)| {
  return (key, some_conversion(value));
}).collect();
如果对两个迭代器进行压缩,例如,也会返回相同的迭代器类型(并且不可收集)。在这种情况下,压缩键,以及仅返回转换值的映射。
new = old.keys().into_iter().zip(old.iter().map(|(key, value)| some_conversion(value)).collect();

最佳答案

问题是iter() ( docs ) 返回一个“非消耗”迭代器,它分发对基础值 ([1]) 的引用。新款HashMap不能使用引用( &String )构造,它需要值( String )。
在您的示例中,some_conversion似乎返回一个新的 String对于值(value)部分,因此应用 .clone()到关键会做的伎俩:

let old: HashMap<String, Value> = some_origin();
let new: HashMap<String, String> = old.iter().map(|(key, value)| {
  return (key.clone(), some_conversion(value));
  //         ^---- .clone() call inserted
}).collect();
Here是 Rust 游乐场上完整示例的链接。
看编译器的错误信息[2],这确实很难弄清楚。我认为对此最有帮助的是在 Rust 中建立关于引用和所有权的直觉,以了解何时引用是可以的以及何时需要拥有的值。
虽然我建议阅读 Rust Book 中关于引用和所有权的部分,甚至更多的 Programming Rust,但要点如下:
  • 通常,Rust 中的值只有一个所有者(异常(exception)是显式共享所有权指针,例如 Rc)。
  • 当一个值被“按值”传递时,它被移动到新位置。这会使值的原始所有者无效。
  • 一个值可以有多个共享引用,但是当存在任何共享引用时,该值是不可变的(不能存在或创建可变引用,因此不能修改或移动它)。
  • 我们不能将值从共享引用中移出(这会使原始所有者无效,当共享引用存在时,该所有者是不可变的)。
  • 通常,即使可以,Rust 也不会自动复制(用 Rust 的说法是“克隆”)值。相反,它需要值(value)的所有权。 (异常(exception)是“Copy ”类型,它们的复制成本很低,例如 i32 )。
  • (此处不相关)也可以有一个对值的可变引用。当这个可变引用退出时,不能创建共享引用。

  • 这有什么帮助?
  • 谁拥有哈希映射中的键?哈希映射可以(规则 1)!
  • 但是我们如何将新的键值对放入哈希映射中呢?这些值被移动到哈希映射中(规则 2)。
  • 但是我们不能移出共享引用...(规则 3 + 规则 4)
  • 而且 Rust 不想克隆值,除非我们告诉它这样做(规则 5)
  • ...所以我们必须自己克隆它。

  • 我希望这能提供一些直觉(我再次真正推荐 Rust 编程)。一般来说,如果你做某事具有值(value),你要么拥有它的所有权,要么得到一个引用。如果您取得所有权,则无法再使用拥有所有权的原始变量。如果您获得引用,则不能将所有权交给其他人(无需克隆)。而 Rust 不会为你克隆。
    [1]:文档称其为“以任意顺序访问所有键值对的迭代器。迭代器元素类型为 (&'a K, &'a V)”。忽略 'a生命周期参数,可以看到元素类型为(&K, &V) .
    [2]:
    13 |         .collect();
       |          ^^^^^^^ value of type `std::collections::HashMap<std::string::String, std::string::String>` cannot be built from `std::iter::Iterator<Item=(&std::string::String, std::string::String)>`
       |
       = help: the trait `std::iter::FromIterator<(&std::string::String, std::string::String)>` is not implemented for `std::collections::HashMap<std::string::String, std::string::String>`
    

    关于Rust 从迭代器中收集 HashMap ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63173420/

    相关文章:

    rust - 将 String::as_str 传递给 Option<String>::map() 无法编译,并出现类型不匹配错误

    rust - 如何将 `aarch64-none-elf` 添加到我的 Rust 工具链?

    rust - 允许多态变量吗?

    lambda - 搜索不一致行为 java-8 流的示例?

    rust - Rust:如何限制Iterator::next()的生存期?

    c++ - 如何在 C++ 中使用行和列获取 map 中元素的值?

    rust - 有没有办法将变量绑定(bind)到 tower-http/hyper/axum 中的请求?

    javascript - IE11 中的 Array.map() 错误

    java - 使用 SimpleAdapter 将获取的图像加载到 listView

    c++ - 从嵌套迭代的列表中删除