如何过滤迭代器中调用函数返回 Result::Err 的值?

3

如何迭代一个列表并过滤掉所有响应Result不是Ok的值?我想做类似于filter_map的操作,但它说我需要返回一个Option

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(|name| match_value(*name))
        .filter(|x| x.is_ok())
        .collect::<Vec<_>>();
    println!("{:?}", matching);
}
2个回答

5
如果您想使用Ok中包含的值,请使用Iterator::flat_map,它会将可迭代的值合并为一个迭代器。 OptionResult都实现了IntoIterator
let matching = values
    .iter()
    .flat_map(|name| match_value(*name))
    .collect::<Vec<_>>();

如果您想要原始值,只需使用filter:
let matching = values
    .iter()
    .filter(|&&name| match_value(name).is_ok())
    .collect::<Vec<_>>();

不需导入 Result 模块,它已经是预加载的一部分。


这很接近,但我想要原始值。有没有办法做到这一点? - Rob
@Rob 我不明白。matching的期望值是多少?如果你在问题中包含了这个信息,我们就不用浪费时间了。 - Shepmaster
谢谢您的帮助,您绝对没有浪费我的时间。 - Rob

1

不确定这是否仍然相关,但也许你想要类似这样的东西

let matching = values
    .iter()
    .filter_map(|name| match_value(*name).ok())
    .collect::<Vec<_>>();

如果出现错误,ok()将返回None,然后被过滤掉。Ok(T)值将转换为原始的T。因此最终,您将拥有一个Vec<T>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接