如何过滤迭代器中返回Result::Err的元素?解决filter_map返回Option问题
解决Rust中过滤迭代器Result::Err元素的问题
其实你找的方向完全没错——filter_map确实是同时完成过滤和值提取的最佳工具,只是需要搭配Result类型自带的一个小方法就能完美解决你的问题!
核心思路
filter_map要求闭包返回Option<T>:返回None的元素会被过滤掉,返回Some(T)的元素会被解包后保留。而Rust的Result正好有一个ok()方法,它能把Ok(v)转换成Some(v),把Err(_)转换成None——这完全适配filter_map的需求!
修改后的完整代码
use std::result::Result; fn match_value(vals: i32) -> Result<i32, i32> { match vals { 2 => Ok(1), _ => Err(0), } } fn main() { let values = vec![1, 2, 3, 2]; let matching = values .iter() .map(|&num| match_value(num)) // 直接解引用迭代器中的&i32为i32 .filter_map(|result| result.ok()) // 自动过滤Err,提取Ok中的值 .collect::<Vec<i32>>(); // 现在收集的是i32类型,而非Result println!("{:?}", matching); // 输出结果:[1, 1] }
额外小技巧:处理Err日志
如果你想在过滤Err的同时记录错误信息(比如调试用),可以在filter_map前加上inspect方法:
let matching = values .iter() .map(|&num| match_value(num)) .inspect(|result| { if let Err(e) = result { eprintln!("过滤掉错误值:{}", e); } }) .filter_map(|result| result.ok()) .collect::<Vec<i32>>();
这样运行时会打印出被过滤的错误,同时不影响最终的结果收集。
对比你原来的代码
你之前的代码用filter(|x| x.is_ok())只能保留Result类型的元素,最终收集的是Vec<Result<i32, i32>>;而用filter_map配合ok(),直接就能得到Vec<i32>,一步完成过滤和值提取,更简洁高效。
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

