【问题标题】:Parsing text file lines into numbers using std::iter::Iterator map使用 std::iter::Iterator 映射将文本文件行解析为数字
【发布时间】:2015-06-02 23:20:27
【问题描述】:

我正在尝试读取和解析 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) =&gt; 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
    });
}

【问题讨论】:

    标签: file text io rust


    【解决方案1】:

    我们看一下complete错误信息,它为我们指出了错误:

    <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() {
                     ^~~~~
    

    编译器期待&amp;Result,但发现Result,问题在于Ok(s) 模式。 l 的类型是对Result引用,因为您使用的是iter - 它会将an iterator of references 返回到向量中的项目。

    最短的解决方法是在闭包变量的模式匹配中添加&amp;

    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 {
    

    为了更好地衡量,您可以使用okand_thenunwrap_or 更简洁地表达同一件事:

    let nums: Vec<i64> = lines.into_iter().map(|l| {
        l.ok().and_then(|s| s.parse().ok()).unwrap_or(0)
    }).collect();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-20
      • 1970-01-01
      • 2016-02-27
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多