我有一个全部以数字开头的字符串列表。然而,我不知道他们的结局是什么。一些示例可能是"12/1/1"、、"33"或"17abc"。我想读取每个字符串开头的数字,将示例分别转换为12、33、 和17。
我已经让它与下面的代码一起工作。
"12/1/1".chars().take_while(|c| c.is_numeric()).collect::<String>().parse::<usize>()
Run Code Online (Sandbox Code Playgroud)
然而,我确实觉得存在更高效/更清洁的解决方案。一种没有字符串集合和/或不那么冗长的方法。
我不想使用任何外部板条箱。
这取决于你对“更好”的定义。如果您只是想删除不必要的String创建,那么您可以使用atoicrate。
或者,您也可以使用nomcrate,并使用它digit0()来创建您自己的atoi()函数:
// nom = "6.0"
use nom::character::complete::digit0;
use nom::error::Error;
use std::str::FromStr;
fn atoi<F: FromStr>(input: &str) -> Result<F, <F as FromStr>::Err> {
digit0::<_, Error<_>>(input).unwrap().1.parse::<F>()
}
fn main() {
println!("{:?}", atoi::<usize>("12/1/1")); // Prints `Ok(12)`
println!("{:?}", atoi::<usize>("33")); // Prints `Ok(33)`
println!("{:?}", atoi::<usize>("17abc")); // Prints `Ok(17)`
println!("{:?}", atoi::<usize>("abc")); // Prints `Err(ParseIntError { kind: Empty })`
println!("{:?}", atoi::<usize>("")); // Prints `Err(ParseIntError { kind: Empty })`
}
Run Code Online (Sandbox Code Playgroud)
是unwrap()安全的,就好像没有数字一样,Ok仍然返回,空字符串由 处理parse()。
由于您不想使用任何外部板条箱,因此您可以使用find()来获取第一个非数字字符的索引。
请注意,@AlexLarionov 的答案会因溢出而恐慌,而这个则不会。
use std::str::FromStr;
fn atoi<F: FromStr>(input: &str) -> Result<F, <F as FromStr>::Err> {
let i = input.find(|c: char| !c.is_numeric()).unwrap_or_else(|| input.len());
input[..i].parse::<F>()
}
fn main() {
println!("{:?}", atoi::<usize>("12/1/1")); // Prints `Ok(12)`
println!("{:?}", atoi::<usize>("33")); // Prints `Ok(33)`
println!("{:?}", atoi::<usize>("17abc")); // Prints `Ok(17)`
println!("{:?}", atoi::<usize>("abc")); // Prints `Err(ParseIntError { kind: Empty })`
println!("{:?}", atoi::<usize>("")); // Prints `Err(ParseIntError { kind: Empty })`
println!("{:?}", atoi::<usize>("123456789101112131415"));
// Prints `Err(ParseIntError { kind: PosOverflow })`
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3111 次 |
| 最近记录: |