我正在试着找出阅读文件内容的最佳方式.问题是我需要单独读取第一行,因为我需要将其解析为usize,这是我需要的Array2乘以ndarray的维度.

我try 了以下几种方法:

use ndarray::prelude::*;
use std::io:{BufRead,BufReader};
use std::fs;


fn read_inputfile(geom_filename: &str) -> (Vec<i32>, Array2<f64>, usize) {
    //* Step 1: Read the coord data from input
    println!("Inputfile: {geom_filename}");

    let geom_file = fs::File::open(geom_filename).expect("Geometry file not found!");
    let geom_file_reader = BufReader::new(geom_file);
    let geom_file_lines: Vec<String> = geom_file_reader
        .lines()
        .map(|line| line.expect("Failed to read line!"))
        .collect();

    //* Read no of atoms first for array size
    let no_atoms: usize = geom_file_lines[0].parse().unwrap();

    let mut Z_vals: Vec<i32> = Vec::new();
    let mut geom_matr: Array2<f64> = Array2::zeros((no_atoms, 3));

    for (atom_idx, line) in geom_file_lines[1..].iter().enumerate() {
        //* into_iter would do the same
        let line_split: Vec<&str> = line.split_whitespace().collect();

        Z_vals.push(line_split[0].parse().unwrap());

        (0..3).for_each(|cart_coord| {
            geom_matr[(atom_idx, cart_coord)] = line_split[cart_coord + 1].parse().unwrap();
        });
    }

    (Z_vals, geom_matr, no_atoms)
}

这不是有点违背了BufReader的目的吗?我对Rust还比较陌生,所以我可能误解了一些东西,但我认为应该使用BufReader,这样就不需要将整个文件读取到内存中.

对于Vec<String>geom_file_lines,我最喜欢再次将整个文件加载到内存中,对吗?

推荐答案

这不是有点违背了BufReader的目的吗?

是的,这是非常重要的.lines()提供了一个迭代器,因此您可以读取它们without,同时将它们全部加载到内存中.你强迫他们全部进入记忆,正如你所说的collect().

就是不要那样做.使用迭代器作为迭代器.特别是当您稍后通过geom_file_lines[1..].iter()将其back转换为迭代器时.

就像这样:

use ndarray::prelude::*;
use std::fs;
use std::io::{BufRead, BufReader};

pub fn read_inputfile(geom_filename: &str) -> (Vec<i32>, Array2<f64>, usize) {
    //* Step 1: Read the coord data from input
    println!("Inputfile: {geom_filename}");

    let geom_file = fs::File::open(geom_filename).expect("Geometry file not found!");
    let geom_file_reader = BufReader::new(geom_file);
    let mut geom_file_lines = geom_file_reader
        .lines()
        .map(|line| line.expect("Failed to read line!"));

    //* Read no of atoms first for array size
    let no_atoms: usize = geom_file_lines.next().unwrap().parse().unwrap();

    let mut z_vals: Vec<i32> = Vec::new();
    let mut geom_matr: Array2<f64> = Array2::zeros((no_atoms, 3));

    for (atom_idx, line) in geom_file_lines.enumerate() {
        let line_split: Vec<&str> = line.split_whitespace().collect();

        z_vals.push(line_split[0].parse().unwrap());

        (0..3).for_each(|cart_coord| {
            geom_matr[(atom_idx, cart_coord)] = line_split[cart_coord + 1].parse().unwrap();
        });
    }

    (z_vals, geom_matr, no_atoms)
}

您可以在您的for循环中应用相同的逻辑:

    for (atom_idx, line) in geom_file_lines.enumerate() {
        let mut line_split = line.split_whitespace();

        z_vals.push(line_split.next().unwrap().parse().unwrap());

        (0..3).for_each(|cart_coord| {
            geom_matr[(atom_idx, cart_coord)] = line_split.next().unwrap().parse().unwrap();
        });
    }

Rust相关问答推荐

如何在Rust中为具有多个数据持有者的enum变体编写文档 comments ?

交叉术语未正确清除屏幕

关于Rust 中回归的逻辑

如何装箱生命周期相关联的两个对象?

通过使用光标拖动角来绕其中心旋转矩形

如何将像烫手山芋一样不透明的值从一个Enum构造函数移动到下一个构造函数?

如何正确重新排列代码以绕过铁 rust 借入判断器?

Rust 的多态现象.AsRef与Derf

.在 Rust 模块标识符中

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

我可以用 Rust 编写一个不可变变量

实现AsyncWrite到hyper Sender时发生生命周期错误

为什么 File::read_to_end 缓冲区容量越大越慢?

将 `&T` 转换为新类型 `&N`

试图理解 Rust 中的可变闭包

用逗号分隔字符串,但在标记中使用逗号

是否有适当的方法在参考 1D 中转换 2D 数组

当 `T` 没有实现 `Debug` 时替代 `unwrap()`

Abortable:悬而未决的期货?

如何在 Rust 的泛型函​​数中同时使用非拥有迭代器和消费迭代器?