以下代码从标准输入中读取以空格分隔的记录,并将逗号分隔的记录写入标准输出。即使进行了优化构建,它仍然相当缓慢(大约比使用 awk 慢两倍)。
use std::io::BufRead;
fn main() {
let stdin = std::io::stdin();
for line in stdin.lock().lines().map(|x| x.unwrap()) {
let fields: Vec<_> = line.split(' ').collect();
println!("{}", fields.join(","));
}
}
有一个显而易见的改进方法是使用 itertools
在不分配向量的情况下进行连接(collect
调用会导致分配)。然而,我尝试了一种不同的方法:
fn main() {
let stdin = std::io::stdin();
let mut cache = Vec::<&str>::new();
for line in stdin.lock().lines().map(|x| x.unwrap()) {
cache.extend(line.split(' '));
println!("{}", cache.join(","));
cache.clear();
}
}
这个版本试图反复使用同一个向量。不幸的是,编译器报错:
error: `line` does not live long enough
--> src/main.rs:7:22
|
7 | cache.extend(line.split(' '));
| ^^^^
|
note: reference must be valid for the block suffix following statement 1 at 5:39...
--> src/main.rs:5:40
|
5 | let mut cache = Vec::<&str>::new();
| ^
note: ...but borrowed value is only valid for the for at 6:4
--> src/main.rs:6:5
|
6 | for line in stdin.lock().lines().map(|x| x.unwrap()) {
| ^
error: aborting due to previous error
当然有道理:变量 line
仅在 for
循环的主体中存在,而 cache
在迭代间保持对它的指针。 但是那个错误对我来说仍然看起来是虚假的:由于缓存在每次迭代后都被 clear
,所以不能保留对 line
的引用,对吗?如何告诉借用检查器这一点?
line
的引用,对吧?” → 对。但是借用检查如何知道呢? - mcartonline
是一个已分配的String
:即使Vec
缓存起作用,每次迭代仍需要进行新的内存分配。 - Matthieu M.line
,您应该使用read_line
而不是lines
。 - mcarton