Iterar sobre Results

Una operación Iter::map puede fallar, por ejemplo:

fn main() {
    let cadenas = vec!["tofu", "93", "18"];
    let numeros: Vec<_> = cadenas
        .into_iter()
        .map(|s| s.parse::<i32>())
        .collect();
    println!("Resultados: {:?}", numeros);
}

Analicemos las estrategias para manejar esto.

Ignorar los elementos fallidos con filter_map()

filter_map llama a una función y filtra los resultados que son None.

fn main() {
    let cadenas = vec!["tofu", "93", "18"];
    let numeros: Vec<_> = cadenas
        .into_iter()
        .filter_map(|s| s.parse::<i32>().ok())
        .collect();
    println!("Resultados: {:?}", numeros);
}

Fallar toda la operación con collect()

Result implementa FromIter para que un vector de resultados (Vec<Result<T, E>>) se pueda convertir en un resultado con un vector (Result<Vec<T>, E>). Una vez que se encuentra un Result::Err, la iteración terminará.

fn main() {
    let cadenas = vec!["tofu", "93", "18"];
    let numeros: Result<Vec<_>, _> = cadenas
        .into_iter()
        .map(|s| s.parse::<i32>())
        .collect();
    println!("Resultados: {:?}", numeros);
}

Esta misma técnica se puede utilizar con Option.

Recopilar todos los valores válidos y fallas con partition()

fn main() {
    let cadenas = vec!["tofu", "93", "18"];
    let (numeros, errors): (Vec<_>, Vec<_>) = cadenas
        .into_iter()
        .map(|s| s.parse::<i32>())
        .partition(Result::is_ok);
    println!("Números: {:?}", numeros);
    println!("Errores: {:?}", errors);
}

Cuando mires los resultados, notarás que todo todavía está envuelto en Result. Se necesita un poco más de repetición para esto.

fn main() {
    let cadenas = vec!["tofu", "93", "18"];
    let (numeros, errors): (Vec<_>, Vec<_>) = cadenas
        .into_iter()
        .map(|s| s.parse::<i32>())
        .partition(Result::is_ok);
    let numeros: Vec<_> = numeros.into_iter().map(Result::unwrap).collect();
    let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
    println!("Números: {:?}", numeros);
    println!("Errores: {:?}", errors);
}