这是一个产生事物向量的函数(可以工作)但是在那里有一些丑陋的展开,因为它涉及弹出另一个向量。
fn load_into_vec(file_buf: String) -> Vec<Data> {
let mut data_vec: Vec<Data> = Vec::new();
for line_iter in file_buf.lines() {
let mut line_vec: Vec<&str> = line_iter.split(' ').collect();
let (t1, t2, t3, t4): (u32, u32, u32, u32) =
(
/** ANOTHER WAY TO WRITE THIS? **/
line_vec.pop().unwrap().trim().parse::<u32>().ok().unwrap(),
line_vec.pop().unwrap().trim().parse::<u32>().ok().unwrap(),
line_vec.pop().unwrap().trim().parse::<u32>().ok().unwrap(),
line_vec.pop().unwrap().trim().parse::<u32>().ok().unwrap()
);
let mut data_node = Data::new();
data_node.load((t4, t3, t2, t1));
data_vec.push(data_node);
}
data_vec
}
是否有另一种方法可以在不使用unwrap
的情况下重写上述块,或者使用unwrap
以便在遇到None
时不会出现恐慌?
答案 0 :(得分:2)
您可以使用迭代器和match
来编写循环体的更惯用版本。您可以在调用Vec
四次时匹配,而不是收集到中间iter.next()
,以提取您的四个整数。如果其中一个iter.next()
来电没有成功,您就会感到恐慌。
let mut iter = line_iter.split(' ')
.map(str::trim)
.map(str::parse::<u32>)
.map(|s| s.expect("could not parse as u32"))
.fuse();
let tup = match (iter.next(), iter.next(), iter.next(), iter.next()) {
(Some(t1), Some(t2), Some(t3), Some(t4)) => (t1, t2, t3, t4),
_ => panic!("line did not contain at least four numbers"),
};
let mut data_node = Data::new();
data_node.load(tup);
我甚至会改写整个函数:
file_buf.lines()
.map(|line_iter| {
let mut iter = line_iter.split(' ')
.map(str::trim)
.map(str::parse::<u32>)
.map(|s| s.expect("could not parse as u32"))
.fuse();
let tup = match (iter.next(), iter.next(), iter.next(), iter.next()) {
(Some(t1), Some(t2), Some(t3), Some(t4)) => (t1, t2, t3, t4),
_ => panic!("line did not contain at least four numbers"),
};
let mut data_node = Data::new();
data_node.load(tup);
data_node
})
.collect()
更好的方法是让函数返回Result
,表示发生错误的时间:
enum MyError {
NotAnInt,
TooFewNumbers,
TooManyNumbers,
}
fn load_into_vec2(file_buf: String) -> Result<Vec<Data>, MyError> {
file_buf.lines()
.map(|line_iter| {
let mut iter = line_iter.split(' ')
.map(str::trim)
.map(str::parse::<u32>)
.fuse();
match (iter.next(), iter.next(), iter.next(), iter.next()) {
(Some(Ok(t1)), Some(Ok(t2)), Some(Ok(t3)), Some(Ok(t4))) => if iter.next().is_some() {
Err(MyError::TooManyNumbers)
} else {
let mut data_node = Data::new();
data_node.load((t1, t2, t3, t4));
Ok(data_node)
},
(None, _, _, _) |
(_, None, _, _) |
(_, _, None, _) |
(_, _, _, None) => Err(MyError::TooFewNumbers),
(Some(Err(_)), _, _, _) |
(_, Some(Err(_)), _, _) |
(_, _, Some(Err(_)), _) |
(_, _, _, Some(Err(_))) => Err(MyError::NotAnInt),
}
})
.collect()
}