我正在尝试使用CSV crate读取CSV文件并将其所有单元格懒惰地转换为f64
:
use csv::ReaderBuilder; // 1.1.4
fn get_df_iterator(path: &str) {
// Build the CSV reader and iterate over each record casting to f64
let rdr = ReaderBuilder::new()
.delimiter(b'\t')
.from_path(path)
.unwrap();
rdr.into_records().map(|record_result| {
record_result
.unwrap()
.into_iter()
.map(|cell: &str| cell.parse::<f64>().unwrap())
})
}
fn main() {
let m1 = get_df_iterator("df1.csv");
}
playground我读过要在稳定的Rust中返回带有闭包的类型,我们可以使用
Box
es。我已经尝试过:use csv::{Error, ReaderBuilder, StringRecord};
fn get_df_iterator_box(path: &str) -> Box<dyn Iterator<Item = Box<dyn Iterator<Item = f64>>>> {
// Build the CSV reader and iterate over each record.
let rdr = ReaderBuilder::new()
.delimiter(b'\t')
.from_path(path)
.unwrap();
// Returns Box<Iterator<Item = f64>>
let parse_str = |cell: &str| cell.parse::<f64>().unwrap();
let parse_record = |record_result: Result<StringRecord, Error>| {
Box::new(record_result.unwrap().into_iter().map(parse_str))
};
// Box<Iterator<Item = Box<Iterator<Item = f64>>>>
Box::new(rdr.into_records().map(parse_record))
}
fn main() {
let m1 = get_df_iterator_box("df1.csv");
}
error[E0271]: type mismatch resolving `<[closure@src/main.rs:13:24: 15:6] as FnOnce<(std::result::Result<StringRecord, csv::Error>,)>>::Output == Box<(dyn Iterator<Item = f64> + 'static)>`
--> src/main.rs:18:5
|
11 | let parse_str = |cell: &str| cell.parse::<f64>().unwrap();
| ----------------------------------------- the expected closure
...
18 | Box::new(rdr.into_records().map(parse_record))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Map`, found trait object `dyn Iterator`
|
= note: expected struct `Box<Map<StringRecordIter<'_>, [closure@src/main.rs:11:21: 11:62]>>`
found struct `Box<(dyn Iterator<Item = f64> + 'static)>`
= note: required because of the requirements on the impl of `Iterator` for `Map<StringRecordsIntoIter<File>, [closure@src/main.rs:13:24: 15:6]>`
= note: required for the cast to the object type `dyn Iterator<Item = Box<(dyn Iterator<Item = f64> + 'static)>>`
我不明白问题是什么。应该返回一个Box
,其中包含一个迭代器,该迭代器返回Box
的迭代器的f64
。 Here there's another playground与该更新!如果要复制相同的文件,则使用here you can download it。
最佳答案
您可以指定闭包的返回类型,以告诉Rust您正在返回dyn trait
:
let parse_record =
|record_result: Result<StringRecord, Error>| -> Box<dyn Iterator<Item = f64>> {
Box::new(record_result.unwrap().into_iter().map(parse_str))
};
另一种方法是在闭包中显式转换:let parse_record = |record_result: Result<StringRecord, Error>| {
Box::new(record_result.unwrap().into_iter().map(parse_str)) as Box<dyn Iterator<Item = f64>>
};
您可以改为返回 impl trait
而不是使用动态调度,并完全避免这种情况:fn get_iterator(path: &str) -> impl Iterator<Item = impl Iterator<Item = f64>> { ... }
有关返回特征的更多信息,请参见What is the correct way to return an Iterator?。
关于rust - 如何返回盒装迭代器,该盒装迭代器返回f64的盒装迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65007594/