问题
Before updating to a more recent Rust version the following used to work:
fn example(val: &[&str]) {
let parsed_value: Vec<usize> = val
.iter()
.filter_map(|e| e.parse::<usize>())
.collect();
}
However, now the parse method returns a Result
type instead of an Option
and I get the error:
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>`
I could create an Option
through a conditional, but is there a better / cleaner way?
回答1:
Use Result::ok. Types added for clarity:
let res: Result<u8, ()> = Ok(42);
let opt: Option<u8> = res.ok();
println!("{:?}", opt);
For symmetry's sake, there's also Option::ok_or and Option::ok_or_else to go from an Option
to a Result
.
In your case, you have an iterator.
If you'd like to ignore failures, use Iterator::flat_map. Since Result
(and Option
) implement IntoIterator
, this works:
let parsed_value: Vec<usize> = val
.iter()
.flat_map(|e| e.parse())
.collect();
If you'd like to stop on the first failure, you can collect
into one big Result
. This is less obvious, but you can check out the implementors of FromIterator for the full list of collect
-able items.
let parsed_value: Result<Vec<usize>, _> = val
.iter()
.map(|e| e.parse())
.collect();
Of course, you can then convert the one big Result
into an Option
, as the first example shows.
来源:https://stackoverflow.com/questions/28572101/what-is-a-clean-way-to-convert-a-result-into-an-option