Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I filter out an iterator's values where calling a function returns a Result::Err?

How would you iterate through a list and filter out all values where the response Result is not Ok? I want to do something like filter_map, but it is saying I need to return an 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);
}
like image 647
Rob Avatar asked Jan 28 '26 00:01

Rob


2 Answers

If you want the value contained in the Ok, use Iterator::flat_map, which combines iterable values into one iterator. Option and Result both implement IntoIterator:

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

If you want the original value, just use filter:

let matching = values
    .iter()
    .filter(|&&name| match_value(name).is_ok())
    .collect::<Vec<_>>();

There's no need to import Result; it's already part of the prelude.

like image 170
Shepmaster Avatar answered Jan 30 '26 18:01

Shepmaster


Not sure if this is still relevant, but maybe you wanted sth like this

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

In case of an error ok() will return None which is then filtered out. Ok(T) values are converted into the origial T. So in the end, you will have an Vec<T>

like image 44
Peter Avatar answered Jan 30 '26 18:01

Peter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!