具有HashMap查找的迭代器映射.没有任何密钥失败

Syn*_*sso 1 iterator hashmap rust

我有一个String以冒号分隔的值.每个子字符串应该是地图中的键.我想写转换函数StringVec图的值,或失败,如果任意键不存在.

到目前为止,我的尝试还不完整,但我只是迈出了一小步.第一步是将字符串转换为可选u32s 的向量.(这可能不是最好的方法):

fn parse(string: &String, lookup: HashMap<String, u32, FastHasher>) -> Vec<Option<u32>> {
    string.split(":").map(|s: &str| lookup.get(s)).collect()
}
Run Code Online (Sandbox Code Playgroud)

这导致了

error: the trait bound `std::vec::Vec<std::option::Option<u32>>: std::iter::FromIterator<std::option::Option<&u32>>` is not satisfied [--explain E0277]
 --> <anon>:8:52
  |>
8 |>     string.split(":").map(|s: &str| lookup.get(s)).collect()
  |>                                                    ^^^^^^^
note: a collection of type `std::vec::Vec<std::option::Option<u32>>` cannot be built from an iterator over elements of type `std::option::Option<&u32>`
Run Code Online (Sandbox Code Playgroud)

我相信这意味着我需要导入或编写自己的from-iterator行为Option<&u32>,对吧?

在我完成之后,我如何包装OkErr依赖于任何Nones 的存在?

Luk*_*odt 6

HashMap::get()方法返回对映射内部值的可选引用.所以你有一个迭代器Option<&u32>,但你想要一个迭代器Option<u32>.这是通过说:

lookup.get(s).cloned()
//           ^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

这使您当前的代码编译.


要回答你标题中的问题:有一个简洁的小问题FromIterator:

impl<A, V> FromIterator<Option<A>> for Option<V> where V: FromIterator<A>
Run Code Online (Sandbox Code Playgroud)

这意味着,例如,你可以在类型项目收集的迭代器Option<u32>Option<Vec<u32>>.这正是你想要的!所以只需更改您的退货类型:

fn parse(string: &str, lookup: &HashMap<String, u32, FastHasher>) -> Option<Vec<u32>> {
//                                                                   ^^^^^^^^^^^^^^^^
    string.split(":").map(|s| lookup.get(s).cloned()).collect()
}
Run Code Online (Sandbox Code Playgroud)

您可以在操场上尝试工作代码.


另请注意以下与我提出的与问题无关的更改:

  • 现在的string争论&str不是&String.实际上没有任何理由可以&String代替&str,因此后者更适合于更通用.
  • 不需要闭包参数的显式类型注释.
  • 你可能想传递一个引用HashMap,因为你的函数不需要拥有它.