我正在使用Rust csv板条箱读取CSV文件。我想为用户创建一个从CSV中获取x个第一个记录的选项。
给定一个像fn read_records(csv_reader: csv::Reader, max_records: Option<usize>) -> ?这样的函数,我想执行以下操作:
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)
我正在努力让我的代码正常工作,编译器出现了以下错误:
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<_>>`我怎样才能让上面的代码工作呢?
发布于 2019-01-05 04:51:56
当max_records为None时,您必须使用take(std::usize::MAX)。这很烦人,但两个迭代器必须具有相同的类型才能存储在相同的变量中。此外,您添加的.intoIter()没有任何影响,因为您在迭代器上调用它们。
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))
}
};
}发布于 2019-01-05 21:50:27
虽然Nate的答案适用于这种特定情况,但这里更通用的解决方案是使用特征对象。我的印象是这就是您在这里使用Box要做的事情。否则,在Nate的解决方案中,Box的使用完全是多余的。
下面是使用特征对象而不需要执行take(std::usize::MAX)的代码(使用Rust 2018):
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));
}https://stackoverflow.com/questions/54043588
复制相似问题