I am trying to use rayon par_iter
with map
(and enumerate
).
However, the closure returns an Option.
Is there a way to collect the Some value of that option while filtering out Nones?
What I do currently is
let par_iter = seqs.into_par_iter().enumerate().map(|(i, d)| -> Option<(String, usize)> {
let mut rng = thread_rng();
let is_ok = somefunc(d);
if is_ok {
return Some((d, i))
} else {
return None
}
});
let res = par_iter.collect::<Vec<Option<(String, usize)>>>();
let mut output: Vec<(String, usize)> = Vec::new();
for opt in res {
if let Some(d) = opt {
output.push(d);
}
}
where seqs
is Vec<String>
.
Is there a less verbose or more typical way of doing this?
Easy:
let res = seqs
.into_par_iter()
.enumerate()
.map(|(i, d)| -> Option<(String, usize)> {
let mut rng = thread_rng();
let is_ok = somefunc(d);
if is_ok {
return Some((d, i));
} else {
return None;
}
})
.filter_map(std::convert::identity)
.collect::<Vec<(String, usize)>>();
Or:
let res = seqs
.into_par_iter()
.enumerate()
.map(|(i, d)| -> Option<(String, usize)> {
let mut rng = thread_rng();
let is_ok = somefunc(d);
if is_ok {
return Some((d, i));
} else {
return None;
}
})
.flatten()
.collect::<Vec<(String, usize)>>();
From benchmarking using criterion
, the filter_map()
version is 10x faster, so you should probably use it.