且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何返回一个结果,其中包含结果迭代器中的每个错误,而不仅仅是第一个错误?

更新时间:2022-06-14 23:16:50


解开每个 Result

我会使用itertools的 partition_map 避免需要拆包:

I would use itertools' partition_map to avoid the need to unwrap:

use itertools::{Either, Itertools}; // 0.8.0

fn iterator() -> impl Iterator<Item = Result<i32, bool>> {
    vec![Ok(1), Err(false), Ok(2), Err(true), Ok(3)].into_iter()
}

fn example() -> Result<Vec<i32>, Vec<bool>> {
    let (values, errors): (Vec<_>, Vec<_>) = iterator().partition_map(|v| match v {
        Ok(v) => Either::Left(v),
        Err(e) => Either::Right(e),
    });

    if errors.is_empty() {
        Ok(values)
    } else {
        Err(errors)
    }
}

另请参见:

  • What's the most idiomatic way of working with an Iterator of Results?
  • How do I stop iteration and return an error when Iterator::map returns a Result::Err?
  • How do I perform iterator computations over iterators of Results without collecting to a temporary vector?

您还可以使用 Option Result 实施 IntoIterator 可以避免确切的 unwrap 的使用,尽管它仍然处理一个集合两次:

You could also use the fact that Option and Result implement IntoIterator to avoid the exact unwrap, although this still processes one collection twice:

fn example2() -> Result<Vec<i32>, Vec<bool>> {
    let (values, errors): (Vec<_>, Vec<_>) = iterator().partition(|result| result.is_ok());

    if errors.is_empty() {
        Ok(values.into_iter().flat_map(Result::ok).collect())
    } else {
        Err(errors.into_iter().flat_map(Result::err).collect())
    }
}

另请参见:

  • Why does `Option` support `IntoIterator`?