1

假设我有一个f带有签名的函数

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

现在我有一个Vec<u8>,我希望找出这个 Vec 中是否有任何元素的值为fOk(b)并且在这种情况下,返回该值b(并停止计算fVec 的其余部分)。我希望有一个带有签名的功能

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's map, filter,reduce不起作用,因为它们会通过整个 Vec,我想避免。

4

1 回答 1

1

Rayon 的.flat_map(…)方法将应用于f每个元素,将每个返回值视为一个迭代器,并将所有这些结果展平为一个新的迭代器。Results 可以用作一个 (if Ok) 或零 (if Err) 元素的迭代,因此这具有展开Ok结果和丢弃Errs 的效果。然后,您可以申请.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)
    }
}

操场输出

Some(true)
于 2019-05-02T21:07:03.383 回答