首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可选地从CSV获取记录

可选地从CSV获取记录
EN

Stack Overflow用户
提问于 2019-01-05 01:32:07
回答 2查看 191关注 0票数 0

我正在使用Rust csv板条箱读取CSV文件。我想为用户创建一个从CSV中获取x个第一个记录的选项。

给定一个像fn read_records(csv_reader: csv::Reader, max_records: Option<usize>) -> ?这样的函数,我想执行以下操作:

代码语言:javascript
复制
use std::fs::File;
use std::io::BufReader;

use csv as csv_crate;

use self::csv_crate::StringRecordsIntoIter;

/// Read a csv, and print the first n records
fn read_csv_repro(
    mut file: File,
    max_read_records: Option<usize>,
) {
    let mut csv_reader = csv::ReaderBuilder::new()
        .from_reader(BufReader::new(file.try_clone().unwrap()));

    let records: Box<StringRecordsIntoIter<std::io::BufReader<std::fs::File>>> = match max_read_records {
        Some(max) => {
            Box::new(csv_reader.into_records().take(max).into_iter())
        },
        None => {
            Box::new(csv_reader.into_records().into_iter())
        }
    };

    for result in records
    {
        let record = result.unwrap();

        // do something with record, e.g. print values from it to console
        let string: Option<&str> = record.get(0);
        println!("First record is {:?}", string);
    }
}

fn main() {
    read_csv_repro(File::open("csv_test.csv").unwrap(), Some(10));
}

(gist)

我正在努力让我的代码正常工作,编译器出现了以下错误:

代码语言:javascript
复制
error[E0308]: mismatched types
  --> src/main.rs:18:22
   |
18 |             Box::new(csv_reader.into_records().take(max).into_iter())
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `csv::reader::StringRecordsIntoIter`, found struct `std::iter::Take`
   |
   = note: expected type `csv::reader::StringRecordsIntoIter<_>`
              found type `std::iter::Take<csv::reader::StringRecordsIntoIter<_>>`

我怎样才能让上面的代码工作呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-05 04:51:56

max_recordsNone时,您必须使用take(std::usize::MAX)。这很烦人,但两个迭代器必须具有相同的类型才能存储在相同的变量中。此外,您添加的.intoIter()没有任何影响,因为您在迭代器上调用它们。

代码语言:javascript
复制
fn read_csv_repro(file: File, max_read_records: Option<usize>) {
    let mut csv_reader = csv::Reader::from_reader(BufReader::new(file));
    let records: Box<std::iter::Take<StringRecordsIntoIter<std::io::BufReader<std::fs::File>>>> = match max_read_records {
        Some(max) => {
            Box::new(csv_reader.into_records().take(max))
        },
        None => {
            Box::new(csv_reader.into_records().take(std::usize::MAX))
        }
    };
}
票数 0
EN

Stack Overflow用户

发布于 2019-01-05 21:50:27

虽然Nate的答案适用于这种特定情况,但这里更通用的解决方案是使用特征对象。我的印象是这就是您在这里使用Box要做的事情。否则,在Nate的解决方案中,Box的使用完全是多余的。

下面是使用特征对象而不需要执行take(std::usize::MAX)的代码(使用Rust 2018):

代码语言:javascript
复制
use std::fs::File;
use std::io::BufReader;

/// Read a csv, and print the first n records
fn read_csv_repro(
    file: File,
    max_read_records: Option<usize>,
) {
    let csv_reader = csv::ReaderBuilder::new()
        .from_reader(BufReader::new(file.try_clone().unwrap()));

    let records: Box<Iterator<Item=csv::Result<csv::StringRecord>>> =
        match max_read_records {
            Some(max) => {
                Box::new(csv_reader.into_records().take(max).into_iter())
            },
            None => {
                Box::new(csv_reader.into_records().into_iter())
            }
        };

    for result in records
    {
        let record = result.unwrap();

        // do something with record, e.g. print values from it to console
        let string: Option<&str> = record.get(0);
        println!("First record is {:?}", string);
    }
}

fn main() {
    read_csv_repro(File::open("csv_test.csv").unwrap(), Some(10));
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54043588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档