Iterating over Results

An Iter::map operation might fail, for example:

  1. fn main() {
  2. let strings = vec!["tofu", "93", "18"];
  3. let possible_numbers: Vec<_> = strings
  4. .into_iter()
  5. .map(|s| s.parse::<i32>())
  6. .collect();
  7. println!("Results: {:?}", possible_numbers);
  8. }

Let’s step through strategies for handling this.

Ignore the failed items with filter_map()

filter_map calls a function and filters out the results that are None.

  1. fn main() {
  2. let strings = vec!["tofu", "93", "18"];
  3. let numbers: Vec<_> = strings
  4. .into_iter()
  5. .map(|s| s.parse::<i32>())
  6. .filter_map(Result::ok)
  7. .collect();
  8. println!("Results: {:?}", numbers);
  9. }

Fail the entire operation with collect()

Result implements FromIter so that a vector of results (Vec<Result<T, E>>)
can be turned into a result with a vector (Result<Vec<T>, E>). Once an
Result::Err is found, the iteration will terminate.

  1. fn main() {
  2. let strings = vec!["tofu", "93", "18"];
  3. let numbers: Result<Vec<_>, _> = strings
  4. .into_iter()
  5. .map(|s| s.parse::<i32>())
  6. .collect();
  7. println!("Results: {:?}", numbers);
  8. }

This same technique can be used with Option.

Collect all valid values and failures with partition()

  1. fn main() {
  2. let strings = vec!["tofu", "93", "18"];
  3. let (numbers, errors): (Vec<_>, Vec<_>) = strings
  4. .into_iter()
  5. .map(|s| s.parse::<i32>())
  6. .partition(Result::is_ok);
  7. println!("Numbers: {:?}", numbers);
  8. println!("Errors: {:?}", errors);
  9. }

When you look at the results, you’ll note that everything is still wrapped in
Result. A little more boilerplate is needed for this.

  1. fn main() {
  2. let strings = vec!["tofu", "93", "18"];
  3. let (numbers, errors): (Vec<_>, Vec<_>) = strings
  4. .into_iter()
  5. .map(|s| s.parse::<i32>())
  6. .partition(Result::is_ok);
  7. let numbers: Vec<_> = numbers.into_iter().map(Result::unwrap).collect();
  8. let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
  9. println!("Numbers: {:?}", numbers);
  10. println!("Errors: {:?}", errors);
  11. }