rust - 如何返回盒装迭代器,该盒装迭代器返回f64的盒装迭代器?

标签 rust

我正在尝试使用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的迭代器的f64Here 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/

相关文章:

rust - 错误 "closure may outlive the current function"的真正含义是什么?

rust - DataFusion(Apache Arrow): How to lazily read batches of result?

memory - Rust-对象的运行时内存大小

rust - 在嵌套循环中修改结构的 Rust 方法是什么?

rust - 为什么编译器要求我在此处添加 return 语句?

rust - 为什么双重反转迭代器的行为就好像它从未被反转过一样?

rust - 通过 Rust 宏自定义文字?

rust - 如何专门针对特定泛型类型的方法?

rust - 为什么特征 `core::fmt::Show` 没有为类型 `core::fmt::Show + Sized` 实现?

iterator - 闭包使局部变量的所有权保持比预期更长的时间