Both of the following work (in 2 invocations), but they feel too verbose.
fn main() {
let v = vec![Some(0), Some(1), None, Some(2)];
assert_eq!(
vec![0,2,4],
v.iter()
.filter(|x| x.is_some())
.map(|x| x.unwrap() * 2)
.collect::<Vec<u8>>());
assert_eq!(
vec![0,2,4],
v.iter()
.filter_map(|x| *x)
.map(|x| x*2)
.collect::<Vec<u8>>());
}
filter_map is close to what I want:
[filter_map] removes the Option layer automatically. If your mapping is already returning an Option and you want to skip over Nones, then filter_map is much, much nicer to use.
doc.rust-lang.org
But it doesn't unwrap the value in the closure because it expects an Option to be returned.
Is there a way to both filter on only the Some values, and map over those values with a single invocation? Such as:
// Fake, does not work
fn main() {
let v = vec![Some(0), Some(1), None, Some(2)];
assert_eq!(
vec![0,2,4],
v.iter()
.map_only_some(|x| x * 2)
.collect::<Vec<u8>>());
}
Well I figured it out, and Iterator's next always returns an Option, so you just have to flatten it:
// Since v.iter().next() is Some(Some(0)), the following works
assert_eq!(
vec![0,2,4],
v.iter()
.flatten()
.map(|x| x * 2)
.collect::<Vec<u8>>());
It's not in a single invocation, but it's much much cleaner and, I think, idiomatic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With