rust - 使用 to_string 是按行读取文件并按空格分割的最干净的方法吗?
问题描述
我正在尝试读取格式如下的文件:
ruby 2.6.2
elixir 1.8.3
并像这样的伪代码转换成二维数组:
[
["ruby", "2.6.2"]
["elixir", "1.8.3"]
]
我必须在 Rust 中执行此操作的代码是:
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::Path;
pub fn present() -> bool {
path().exists()
}
pub fn parse() -> Vec<Vec<String>> {
let f = BufReader::new(file().unwrap());
f.lines()
.map(|line| {
line.unwrap()
.split_whitespace()
.map(|x| x.to_string())
.collect()
})
.collect()
}
fn file() -> io::Result<File> {
let f = File::open(path())?;
return Ok(f);
}
fn path<'a>() -> &'a Path {
return Path::new(".tool-versions");
}
我在这里不确定的是parse
函数中间的这一行:
.map(|x| x.to_string())
这似乎有点“过度劳累”,但我不确定我的感觉是否正确。
我在这里遗漏了什么,或者这是编写此代码以完成此特定任务的最干净的方法?
解决方案
您的代码通常是惯用的并且很好,我只是有一些小警告。
至于“过度工作”,我认为就地修改字符串是过度工作,因为在每个删除的空白字符处,您都需要做以下三件事之一:
- 将超过该元素的每个字符向下移动 1(大多数移动,但不需要分配)。
- 存储每个位置的索引,以相反的顺序迭代并将每个元素向下移动 1(更少移动,但需要分配)。
- 存储每个位置的索引,跟踪起始当前空白块的索引,当前空白块的结束和下一个块的开始,并向下移动每个元素,然后跟踪这些移位(最复杂,需要最少的移动,并且比需要的计算成本更高)。
或者..你可以分配一个新的字符串。有时简单是强大的。
对于其余部分,一个主要问题是不要不必要地恐慌,尤其是不要因为无法打开文件而感到恐慌。展开,除非你能证明它们不应该发生,否则不适合生产代码。具体来说,以下行可能会引起恐慌。
let f = BufReader::new(file().unwrap());
最好将该功能替换为:
pub fn parse() -> io::Result<Vec<Vec<String>>> {
let f = BufReader::new(file()?);
f.lines()
.map(|line| {
line.map(|x| {
x
.split_whitespace()
.map(|x| x.to_string())
.collect()
})
})
.collect()
}
这样,调用者parse
可以适当地处理任何错误,无论是在创建 BufReader 期间还是在lines()
.
推荐阅读
- html - Django URL 显示上一个和当前页面,但我只想要 URL 中的当前页面名称
- python - 属性错误:模块 tensorflow 没有属性“get_default_graph”?
- delphi - Firemonkey TFrame - 如何触发祖先 TFrame 事件?
- javascript - 是否可以将父div中的所有项目都放在列中
- java - 在 C/C++ 中获取 Kerberos 票证
- reactjs - React 转换转换组问题。想做一个简单的动画,但是不行
- r - R - 创建数据集,显示两个相似数据集之间的增量/进度
- python - DataFrameA.columnA 与 Pandas 中的 DataFrameA.["columnA"] 相同吗?
- amazon-web-services - 从 url 将(一批)文件直接下载到 AWS s3 存储桶
- java - 使用 vladmihalcea JsonBinaryType 时获取“JDBC 类型的无方言映射:1111”