具有HashMap查找的迭代器映射。在任何不存在的密钥上失败

具有HashMap查找的迭代器映射。在任何不存在的密钥上失败,hashmap,iterator,rust,Hashmap,Iterator,Rust,我有一个以冒号分隔的字符串。每个子字符串都应该是映射中的一个键。我想编写一个函数,将字符串转换为映射值的Vec,如果没有任何键,则会导致失败 到目前为止,我的尝试是不完整的,但我正在小步进行。第一步是将字符串转换为可选U32的向量。这可能不是最好的方法: fn parse(string: &String, lookup: HashMap<String, u32, FastHasher>) -> Vec<Option<u32>> { str

我有一个以冒号分隔的字符串。每个子字符串都应该是映射中的一个键。我想编写一个函数,将字符串转换为映射值的Vec,如果没有任何键,则会导致失败

到目前为止,我的尝试是不完整的,但我正在小步进行。第一步是将字符串转换为可选U32的向量。这可能不是最好的方法:

fn parse(string: &String, lookup: HashMap<String, u32, FastHasher>) -> Vec<Option<u32>> {
    string.split(":").map(|s: &str| lookup.get(s)).collect()
}
这导致

错误:特性绑定'std::vec::vec:std::iter::FromIterator'不满足[-explain E0277] -> :8:52 |> 8 |>string.split:.map | s:&str | lookup.get.collect |> ^^^^^^^ 注意:不能通过迭代器在'std::option::option'类型的元素上构建'std::vec::vec'类型的集合` 我相信这意味着我需要从迭代器行为导入或编写我自己的选项,对吗


完成此操作后,我如何根据是否存在任何“非”来包装“确定”或“错误”?

为了避免此问题,您可以直接返回Vec而不是Vec:

如果你把它包装成一个结果,我不确定它是否会增加价值;之后,您可以轻松检查是否没有:

let v = vec![Some(1), None, Some(3)];
println!("{:?}", v.contains(&None));

为了避免此问题,您可以直接返回Vec,而不是Vec:

如果你把它包装成一个结果,我不确定它是否会增加价值;之后,您可以轻松检查是否没有:

let v = vec![Some(1), None, Some(3)];
println!("{:?}", v.contains(&None));
该方法返回对映射内部值的可选引用。所以您有一个迭代器覆盖选项,但您希望有一个迭代器覆盖选项。这是通过以下方式实现的:

lookup.get(s).cloned()
//           ^^^^^^^^^
这将使您当前的代码可以编译

要回答标题中的问题:有一个简洁的小提示:

这意味着,例如,您可以将选项类型项上的迭代器收集到选项中。这正是你想要的!因此,只需更改您的退货类型:

fn parse(string: &str, lookup: &HashMap<String, u32, FastHasher>) -> Option<Vec<u32>> {
//                                                                   ^^^^^^^^^^^^^^^^
    string.split(":").map(|s| lookup.get(s).cloned()).collect()
}
您可以尝试工作代码

还请注意我所做的以下独立于问题的更改:

字符串参数现在是&str,而不是&string。实际上没有理由传递&String而不是&str,因此后者更通用。 闭包参数的显式类型注释不是必需的。 您可能希望传递对HashMap的引用,因为您的函数不需要拥有它。 该方法返回对映射内部值的可选引用。所以您有一个迭代器覆盖选项,但您希望有一个迭代器覆盖选项。这是通过以下方式实现的:

lookup.get(s).cloned()
//           ^^^^^^^^^
这将使您当前的代码可以编译

要回答标题中的问题:有一个简洁的小提示:

这意味着,例如,您可以将选项类型项上的迭代器收集到选项中。这正是你想要的!因此,只需更改您的退货类型:

fn parse(string: &str, lookup: &HashMap<String, u32, FastHasher>) -> Option<Vec<u32>> {
//                                                                   ^^^^^^^^^^^^^^^^
    string.split(":").map(|s| lookup.get(s).cloned()).collect()
}
您可以尝试工作代码

还请注意我所做的以下独立于问题的更改:

字符串参数现在是&str,而不是&string。实际上没有理由传递&String而不是&str,因此后者更通用。 闭包参数的显式类型注释不是必需的。 您可能希望传递对HashMap的引用,因为您的函数不需要拥有它。
如果确实要返回引用,则应明确指定生存期:

pub fn parse<'a, 'b>(string: &'a str, lookup: &'b HashMap<String, u32>) -> Vec<Option<&'b u32>> {
    string.split(":").map(|s| lookup.get(s)).collect()
}

如果确实要返回引用,则应明确指定生存期:

pub fn parse<'a, 'b>(string: &'a str, lookup: &'b HashMap<String, u32>) -> Vec<Option<&'b u32>> {
    string.split(":").map(|s| lookup.get(s)).collect()
}

您忘了返回类型了吗?我省略了它,以查看语句的实际问题。我在这段代码的某个远距离迭代中有一个返回类型。已更新。您忘记返回类型了吗?我省略了它,以查看语句的实际问题。我在这段代码的某个远距离迭代中有一个返回类型。更新。注意:您可以使用Option::cloned从一个选项移动到另一个选项,这会缩短代码:string.split:.map | s:&str | lookup.gets.cloned.Collects不知道,非常方便;我会将其包含在答案中。注意:您可以使用Option::cloned从一个选项移动到另一个选项,这会缩短代码:string.split:.map | s:&str | lookup.get.cloned.collect不知道这一点,非常方便;我会把它包括在答案中。