在Rust中如何对Result类型的Vec做分区,实现类似partitionEithers的功能
实现方案
标准库中 Result 的 FromIterator 实现仅支持遇到第一个错误就提前返回的场景,也就是你之前用到的 collect::<Result<Vec<A>, B>> 的逻辑,默认不会收集所有错误,因此不存在直接生成 Result<Vec<A>, Vec<B>> 的内置 collect 实现。
你可以用迭代器的 fold 方法实现需求,不需要手动维护外部可变变量,属于符合要求的不可变实现:
fn partition_results<A, B>(input: Vec<Result<A, B>>) -> Result<Vec<A>, Vec<B>> { let (oks, errs): (Vec<_>, Vec<_>) = input .into_iter() .fold((Vec::new(), Vec::new()), |(mut oks, mut errs), item| { match item { Ok(val) => oks.push(val), Err(e) => errs.push(e), } (oks, errs) }); errs.is_empty().then_some(oks).ok_or(errs) }
如果可以引入第三方依赖,使用 itertools 库的 partition_map 方法可以进一步简化代码:
use itertools::Itertools; fn partition_results<A, B>(input: Vec<Result<A, B>>) -> Result<Vec<A>, Vec<B>> { let (oks, errs): (Vec<A>, Vec<B>) = input .into_iter() .partition_map(|res| res.into()); errs.is_empty().then_some(oks).ok_or(errs) }
两种方案都满足对应功能:输入的 Vec 中所有值都是 Ok 时返回包含全部 Ok 内容的 Result::Ok,只要存在至少一个 Err 就返回包含全部错误内容的 Result::Err。
内容的提问来源于stack exchange,提问作者Wong Jia Hau
相关产品推荐
相关产品推荐

