Convert iterator of Result into Result of iterator

When working with iterators in Rust, especially in a functional style using methods like map, filter, or filter_map, you might end up with an iterator of Result types, i.e., Iterator<Item = Result<T, E>>. However, you may often want to check if there were any errors and, if none, iterate over the underlying Ok values. Fortunately, calling .collect() on such an iterator with a Result<_, _> as the target type will do exactly that: it collects the Ok values or returns the first encountered error.

Example

fn main() {
    // Vectors witout and with errors.
    let without_errs = vec![Ok(1), Ok(2), Ok(4)];
    let with_errs = vec![Ok(1), Ok(2), Err("this is error"), Ok(4)];

    // Convert iterator of Resultsi into a Result of iterators.
    let without_errs: Result<Vec<_>, &'static str> = without_errs.into_iter().collect();
    let with_errs: Result<Vec<_>, &'static str> = with_errs.into_iter().collect();

    println!("Without: {without_errs:?}");
    println!("With   : {with_errs:?}");
    // The output:
    // Without: Ok([1, 2, 4])
    // With   : Err("this is error")
}

In this example, we have two vectors of type Result<u32, &'static str>. The first vector contains no error values, while the second vector includes an error value. When we collect these into a Result<Vec<_>, &'static str>, the first vector collects all values successfully, whereas in the second case, we receive the first error encountered. You can experiment with variations, such as having multiple errors or working with an empty iterator, to see what happens in those scenarios.

Note that this approach also works with other collections besides vectors, such as HashMap, HashSet, or any other collection that implements the FromIterator trait.

Extra points: not collecting the iterator

If you want to access the iterator without using collect, you can use the process_results function from the itertools crate. This function allows you to work with the values directly as an iterator of Ok values. However, keep in mind that the entire iterator must still be iterated through to ensure there are no errors, as process_results will stop and return the first error it encounters.

©2023‐2024hack nota