Rayon find_any и возвращает значение найденного элемента - PullRequest
1 голос
/ 02 мая 2019

Допустим, у меня есть функция f с подписью

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

Теперь у меня есть Vec<u8>, и я хочу выяснить, есть ли в этом Vec какой-либо элемент, значение которого f равно Ok(b), и, в этом случае, верните значение b (и прекратите вычисление f для остальной части Vec).Я хочу иметь функцию с подписью

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, чего я хочу избежать.

1 Ответ

1 голос
/ 03 мая 2019

Метод Района .flat_map(…) будет применять f к каждому элементу, обрабатывать каждое возвращаемое значение как итератор и объединять все эти результаты в один новый итератор. Result s может использоваться как итерация одного (если Ok) или нуля (если Err) элементов , так что это приводит к развертыванию Ok результатов и отбрасыванию Err s , Затем вы можете применить .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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...