使用 std::iter::Iterator 映射将文本文件行解析为数字
Parsing text file lines into numbers using std::iter::Iterator map
我正在尝试读取和解析 Rust 中的文本文件。每行都是一个带符号的整数。我可以使用 for line in lines
迭代来完成,但我无法使用 iter().map(|l| ...)
单行代码来完成。我得到一个
expected `&core::result::Result<collections::string::String, std::io::error::Error>`,
found `core::result::Result<_, _>`
当我尝试模式匹配时 Ok(s) => match s.parse()
但我无法深入了解我做错了什么。整个例子如下。底部的代码是产生错误的代码。
谁能告诉我哪里做错了?
use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
fn main() {
// Create a path to the desired file
let path = Path::new("input/numbers.txt");
let display = path.display();
// Open the path in read-only mode, returns `io::Result<File>`
let file = match File::open(&path) {
// The `description` method of `io::Error` returns a string that describes the error
Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
Ok(file) => file,
};
// Collect all lines into a vector
let reader = BufReader::new(file);
let lines: Vec<_> = reader.lines().collect();
// Works.
let mut nums = vec![];
for l in lines {
println!("{:?}", l);
let num = match l {
Ok(s) => match s.parse() {
Ok(i) => i,
Err(_) => 0
},
Err(_) => 0
};
nums.push(num);
}
// Doesn't work!
let nums: Vec<i64> = lines.iter().map(|l| match l {
Ok(s) => match s.parse() {
Ok(i) => i,
Err(_) => 0
},
Err(_) => 0
});
}
我们来看一下完整的错误信息,它为我们指出了错误:
<anon>:5:9: 5:14 error: mismatched types:
expected `&core::result::Result<&str, ()>`,
found `core::result::Result<_, _>`
(expected &-ptr,
found enum `core::result::Result`) [E0308]
<anon>:5 Ok(s) => match s.parse() {
^~~~~
编译器期望 &Result
,但找到了 Result
,问题出在 Ok(s)
模式上。 l
的类型是对 Result
的 reference,因为您正在对向量中的项目使用 iter
- which returns an iterator of references。
最短的解决方法是在闭包变量的模式匹配中添加 &
:
fn main() {
let lines: Vec<Result<_, ()>> = vec![Ok("1"), Ok("3"), Ok("5")];
// HERE V
let nums: Vec<i64> = lines.iter().map(|&l| match l {
Ok(s) => match s.parse() {
Ok(i) => i,
Err(_) => 0
},
Err(_) => 0
}).collect();
println!("{:?}", nums)
}
我还必须添加 collect
才能返回到 Vec
。
您可以进行的其他更改是使用 into_iter
消耗 输入向量,然后迭代向量中的每个值:
// HERE V~~~~
let nums: Vec<i64> = lines.into_iter().map(|l| match l {
为了更好的衡量,您可以使用 ok
, and_then
, and unwrap_or
更简洁地表达同样的事情:
let nums: Vec<i64> = lines.into_iter().map(|l| {
l.ok().and_then(|s| s.parse().ok()).unwrap_or(0)
}).collect();
我正在尝试读取和解析 Rust 中的文本文件。每行都是一个带符号的整数。我可以使用 for line in lines
迭代来完成,但我无法使用 iter().map(|l| ...)
单行代码来完成。我得到一个
expected `&core::result::Result<collections::string::String, std::io::error::Error>`,
found `core::result::Result<_, _>`
当我尝试模式匹配时 Ok(s) => match s.parse()
但我无法深入了解我做错了什么。整个例子如下。底部的代码是产生错误的代码。
谁能告诉我哪里做错了?
use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::Path;
fn main() {
// Create a path to the desired file
let path = Path::new("input/numbers.txt");
let display = path.display();
// Open the path in read-only mode, returns `io::Result<File>`
let file = match File::open(&path) {
// The `description` method of `io::Error` returns a string that describes the error
Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
Ok(file) => file,
};
// Collect all lines into a vector
let reader = BufReader::new(file);
let lines: Vec<_> = reader.lines().collect();
// Works.
let mut nums = vec![];
for l in lines {
println!("{:?}", l);
let num = match l {
Ok(s) => match s.parse() {
Ok(i) => i,
Err(_) => 0
},
Err(_) => 0
};
nums.push(num);
}
// Doesn't work!
let nums: Vec<i64> = lines.iter().map(|l| match l {
Ok(s) => match s.parse() {
Ok(i) => i,
Err(_) => 0
},
Err(_) => 0
});
}
我们来看一下完整的错误信息,它为我们指出了错误:
<anon>:5:9: 5:14 error: mismatched types:
expected `&core::result::Result<&str, ()>`,
found `core::result::Result<_, _>`
(expected &-ptr,
found enum `core::result::Result`) [E0308]
<anon>:5 Ok(s) => match s.parse() {
^~~~~
编译器期望 &Result
,但找到了 Result
,问题出在 Ok(s)
模式上。 l
的类型是对 Result
的 reference,因为您正在对向量中的项目使用 iter
- which returns an iterator of references。
最短的解决方法是在闭包变量的模式匹配中添加 &
:
fn main() {
let lines: Vec<Result<_, ()>> = vec![Ok("1"), Ok("3"), Ok("5")];
// HERE V
let nums: Vec<i64> = lines.iter().map(|&l| match l {
Ok(s) => match s.parse() {
Ok(i) => i,
Err(_) => 0
},
Err(_) => 0
}).collect();
println!("{:?}", nums)
}
我还必须添加 collect
才能返回到 Vec
。
您可以进行的其他更改是使用 into_iter
消耗 输入向量,然后迭代向量中的每个值:
// HERE V~~~~
let nums: Vec<i64> = lines.into_iter().map(|l| match l {
为了更好的衡量,您可以使用 ok
, and_then
, and unwrap_or
更简洁地表达同样的事情:
let nums: Vec<i64> = lines.into_iter().map(|l| {
l.ok().and_then(|s| s.parse().ok()).unwrap_or(0)
}).collect();