看下面的示例,你会发现Iter::map在处理过程中会失败:
fn main() {
let strings = vec!["tofu", "93", "18"];
let numbers: Vec<_> = strings
.into_iter()
.map(|s| s.parse::<i32>())
.collect();
println!("Results: {:?}", numbers);
}
让我们逐步讨论处理这种错误的策略。
使用filter_map()来过滤掉失败的子项
filter_map()调用一个函数来过滤掉结果是None的子项:
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);
}
使用map_err()和filter_map()收集错误的子项
map_err()可以调用错误处理函数,把它放入filter_map()函数内,正好可以处理过滤出的错误。
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);
}
只使用collect(),当有错时,会导致整个失败
Result实现了FromIterator,因此result的集合(Vec<Result<t,E>>)可以被转换为包含结合的Result(Result<Vec<T>,E>)。一旦出现了Result::Err,整个遍历就会终止。
fn main() {
let strings = vec!["tofu", "93", "18"];
let numbers: Result<Vec<_>, _> = strings
.into_iter()
.map(|s| s.parse::<i32>())
.collect();
println!("Results: {:?}", numbers);
}
Option也可以这样操作。
使用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);
}
当你查看结果时,会发现每个子项都会包裹在Result内。这时就需要标准模板代码来进行解包了:
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);
}