什么是一个干净的方法来转换一个结果到一个选项?

在更新到最新的 Rust 版本之前,下面的代码可以正常工作:

fn example(val: &[&str]) {
let parsed_value: Vec<usize> = val
.iter()
.filter_map(|e| e.parse::<usize>())
.collect();
}

但是,现在 parse 方法返回的是 Result类型,而不是 Option类型,我得到了错误:

error[E0308]: mismatched types
--> src/lib.rs:4:25
|
4 |         .filter_map(|e| e.parse::<usize>())
|                         ^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
= note: expected type `std::option::Option<_>`
found type `std::result::Result<usize, std::num::ParseIntError>`

我可以通过一个条件来创建一个 Option,但是有没有更好/更干净的方法呢?

37294 次浏览

使用 Result::ok。为清晰起见添加了类型:

let res: Result<u8, ()> = Ok(42);
let opt: Option<u8> = res.ok();
println!("{:?}", opt);

为了对称起见,还有 Option::ok_orOption::ok_or_else可以从 Option变成 Result


在您的例子中,您有一个迭代器。

如果您希望 忽略故障,请使用 Iterator::flat_map。由于 Result(和 Option)实现了 IntoIterator,因此可以这样做:

let parsed_value: Vec<usize> = val
.iter()
.flat_map(|e| e.parse())
.collect();

如果你想在第一次失败时停止,你可以把 collect变成一个大的 Result。这一点不太明显,但是您可以查看 FromIterator的实现者以获得 collect-able 项的完整列表。

let parsed_value: Result<Vec<usize>, _> = val
.iter()
.map(|e| e.parse())
.collect();

当然,您可以将一个大的 Result转换成 Option,如第一个示例所示。