Rust Rayon collect Options into Vector

131 views Asked by At

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?

1

There are 1 answers

2
Chayim Friedman On BEST ANSWER

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.