aut*_*eps 6 iterator tuples hashmap rust
我们有一个 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)>`
Run Code Online (Sandbox Code Playgroud)
我们所做的基本上归结为:
let old: HashMap<String, Value> = some_origin();
let new: HashMap<String, String> = old.iter().map(|(key, value)| {
return (key, some_conversion(value));
}).collect();
Run Code Online (Sandbox Code Playgroud)
如果对两个迭代器进行压缩,例如在这种情况下压缩键,并且映射仅返回转换后的值,则也会返回相同的迭代器类型(并且不可收集)。
new = old.keys().into_iter().zip(old.iter().map(|(key, value)| some_conversion(value)).collect();
Run Code Online (Sandbox Code Playgroud)
问题是iter()
(docs)返回一个“非消耗”迭代器,它分发对基础值([1])的引用。newHashMap
不能使用引用 ( &String
)构造,它需要值 ( String
)。
在您的示例中,some_conversion
似乎String
为 value 部分返回了一个 new ,因此应用.clone()
到 key 可以解决问题:
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();
Run Code Online (Sandbox Code Playgroud)
这是 Rust 操场上完整示例的链接。
看编译器的错误信息[2],这确实很难弄清楚。我认为对此最有帮助的是在 Rust 中建立关于引用和所有权的直觉,以了解何时引用是可以的以及何时需要拥有的值。
虽然我建议阅读 Rust Book 中关于引用和所有权的部分,甚至更多的 Programming Rust,但要点如下:
Rc
)。Copy
复制成本低的“ ”类型,例如i32
)。这有什么帮助?
我希望这能提供一些直觉(我再次真正推荐 Rust 编程)。一般来说,如果你做某事具有价值,你要么拥有它的所有权,要么得到一个参考。如果您取得所有权,则无法再使用拥有所有权的原始变量。如果您获得参考,则不能将所有权交给其他人(无需克隆)。而 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>`
Run Code Online (Sandbox Code Playgroud)