Опционально `Take 'записи из CSV - PullRequest
0 голосов
/ 04 января 2019

Я использую ящик Rust csv для чтения файлов CSV. Я хочу создать для пользователя возможность получать x первых записей из CSV.

Учитывая функцию типа 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));
}

( * 1009 суть *)

Я пытаюсь заставить мой код работать, с приведенной ниже ошибкой компилятора:

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<_>>`

Как мне заставить работать приведенный выше код?

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Хотя ответ Нейта подходит для этого конкретного случая, более общее решение здесь заключается в использовании черт объектов. У меня сложилось впечатление, что это то, что вы намеревались сделать, используя Box здесь. В противном случае, в решении Нейта использование 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));
}
0 голосов
/ 04 января 2019

Вы должны take(std::usize::MAX), когда max_records равно None. Это раздражает, но оба итератора должны иметь одинаковый тип для хранения в одной и той же переменной. Кроме того, добавленные вами .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))
        }
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...