首页 > 解决方案 > 解析 TSV 文件 (ASCII) 的惯用方式

问题描述

我需要解析包含制表符分隔数字的文件,我也知道总是只有两个。由于我的文件可能高达几 GB,我想知道我当前的解析方法是否正确。考虑到我的尺寸固定,看起来我可以让地图更快,但我找不到如何做。

use std::io::{self, prelude::*, BufReader};

type Record = (u32, u32);

fn read(content: &[u8]) -> io::Result<Vec<Record>> {
    Ok(BufReader::new(content)
        .lines()
        .map(|line| {
            let nums: Vec<u32> = line
                .unwrap()
                .split("\t")
                .map(|s| s.parse::<u32>().unwrap())
                .collect();
            (nums[0], nums[1])
        })
        .collect::<Vec<Record>>())
}

fn main() -> io::Result<()> {
    let content = "1\t1\n\
                    2\t2\n";
    let records = read(content.as_bytes())?;
    assert_eq!(records.len(), 2);
    assert_eq!(records[0], (1, 1));
    assert_eq!(records[1], (2, 2));
    Ok(())
}

操场

标签: csvrust

解决方案


如果您的条目只是数字,那么我们可以像这样减少一个内部Vec分配map


use std::io::{self, prelude::*, BufReader};

type Record = (u32, u32);

fn read(content: &[u8]) -> io::Result<Vec<Record>> {
    return Ok(BufReader::new(content).lines().map(|line| {
        let line = line.unwrap();
        let mut pair = line.split("\t").map(|s|s.parse::<u32>().unwrap());
        (pair.next().unwrap(), pair.next().unwrap())
    }).collect::<Vec<Record>>())
}

fn main() -> io::Result<()> {
    let content = "1\t1\n\
                    2\t2\n";
    let records = read(content.as_bytes())?;
    assert_eq!(records.len(), 2);
    assert_eq!(records[0], (1, 1));
    assert_eq!(records[1], (2, 2));
    Ok(())
}

您可能想要添加更好的错误处理:)


推荐阅读