Einführung
In diesem Lab untersuchen wir verschiedene Strategien, um die Möglichkeit von Fehlern zu behandeln, während wir über eine Sammlung von Results in Rust iterieren.
Hinweis: Wenn das Lab keinen Dateinamen angibt, können Sie einen beliebigen Dateinamen verwenden. Beispielsweise können Sie
main.rsverwenden und es mitrustc main.rs &&./mainkompilieren und ausführen.
Iterieren über Results
Eine Iter::map-Operation kann fehlschlagen, z.B.:
fn main() {
let strings = vec!["tofu", "93", "18"];
let numbers: Vec<_> = strings
.into_iter()
.map(|s| s.parse::<i32>())
.collect();
println!("Results: {:?}", numbers);
}
Schauen wir uns die Strategien an, um dies zu behandeln.
Ignorieren Sie die fehlgeschlagenen Elemente mit filter_map()
filter_map ruft eine Funktion auf und filtert die Ergebnisse, die None sind.
fn main() {
let strings = vec!["tofu", "93", "18"];
let numbers: Vec<_> = strings
.into_iter()
.filter_map(|s| s.parse::<i32>().ok())
.collect();
println!("Results: {:?}", numbers);
}
Sammeln Sie die fehlgeschlagenen Elemente mit map_err() und filter_map()
map_err ruft eine Funktion mit dem Fehler auf, so dass wir sie, indem wir sie der vorherigen filter_map-Lösung hinzufügen, während des Iterierens beiseite legen können.
fn main() {
let strings = vec!["42", "tofu", "93", "999", "18"];
let mut errors = vec![];
let numbers: Vec<_> = strings
.into_iter()
.map(|s| s.parse::<u8>())
.filter_map(|r| r.map_err(|e| errors.push(e)).ok())
.collect();
println!("Numbers: {:?}", numbers);
println!("Errors: {:?}", errors);
}
Den gesamten Vorgang mit collect() abbrechen
Result implementiert FromIterator, sodass ein Vektor von Ergebnissen (Vec<Result<T, E>>) in ein Ergebnis mit einem Vektor (Result<Vec<T>, E>) umgewandelt werden kann. Sobald ein Result::Err gefunden wird, wird die Iteration abgebrochen.
fn main() {
let strings = vec!["tofu", "93", "18"];
let numbers: Result<Vec<_>, _> = strings
.into_iter()
.map(|s| s.parse::<i32>())
.collect();
println!("Results: {:?}", numbers);
}
Dieselbe Technik kann mit Option verwendet werden.
Sammeln Sie alle gültigen Werte und Fehler mit partition()
fn main() {
let strings = vec!["tofu", "93", "18"];
let (numbers, errors): (Vec<_>, Vec<_>) = strings
.into_iter()
.map(|s| s.parse::<i32>())
.partition(Result::is_ok);
println!("Numbers: {:?}", numbers);
println!("Errors: {:?}", errors);
}
Wenn Sie sich die Ergebnisse ansehen, werden Sie feststellen, dass alles immer noch in Result eingeschlossen ist. Dafür ist ein bisschen mehr Boilerplate erforderlich.
fn main() {
let strings = vec!["tofu", "93", "18"];
let (numbers, errors): (Vec<_>, Vec<_>) = strings
.into_iter()
.map(|s| s.parse::<i32>())
.partition(Result::is_ok);
let numbers: Vec<_> = numbers.into_iter().map(Result::unwrap).collect();
let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
println!("Numbers: {:?}", numbers);
println!("Errors: {:?}", errors);
}
Zusammenfassung
Herzlichen Glückwunsch! Sie haben das Lab Iterieren über Results abgeschlossen. Sie können in LabEx weitere Labs ausprobieren, um Ihre Fähigkeiten zu verbessern.