Rayon find_any 和 return 找到的物品的价值

Rayon find_any, and return the found item's value

假设我有一个带有签名

的函数f
fn f(a: u8) -> Result<bool, SomeError> {}

现在我有一个 Vec<u8>,我想找出这个 Vec 中是否有任何元素,其 f 的值是 Ok(b),在这种情况下,return 值 b(并停止为 Vec 的其余部分计算 f)。我希望有一个带有签名的函数

fn my_function(v: Vec<u8>) -> Option<bool> {}

这是我的第一个实现:

fn my_function(v: Vec<u8>) -> Option<bool> {
  let found = v.par_iter().find_any(|a| f(a).is_ok());

  match found {
    Some(a) => Some(f(a).unwrap()),
    None => None
  }
}

但我最后做了一个无用的 f 计算。我怎样才能重构代码来避免这个额外的 f 调用?

Rayon 的 mapfilterreduce 将不起作用,因为它们会遍历整个 Vec,我想避免这种情况。

Rayon's .flat_map(…) method will apply f to each element, treat each return value as an iterator, and flatten all of those results into a single new iterator. Results can be used as iterables of one (if Ok) or zero (if Err) elements,因此这具有展开 Ok 结果并丢弃 Err 的效果。然后,您可以应用 .find_any(|_| true) 来获取第一个可用的结果值,而无需再次调用 f(…).

use rayon::prelude::*;

fn my_function(v: Vec<u8>) -> Option<bool> {
    v.par_iter().flat_map(|x| f(*x)).find_any(|_| true)
}

fn f(a: u8) -> Result<bool, SomeError> {
    if a == 42 {
        Ok(true)
    } else {
        Err(SomeError {})
    }
}

fn main() {
    println!("{:?}", my_function(vec![0, 1, 2, 42, 3, 42, 0]));
}

#[derive(Debug)]
struct SomeError {}
impl std::error::Error for SomeError {}
impl std::fmt::Display for SomeError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

Playground Output

Some(true)