将Iterator<&str>
转换为String
并穿插一些常量字符串(例如"\n"
)的规范方法是什么?
例如,给定:
let xs = vec!["first", "second", "third"];
let it = xs.iter();
有一种方法可以通过将字符串收集到s
中并Iterable
来生成字符串join
:
let s = it
.map(|&x| x)
.collect::<Vec<&str>>()
.join("\n");
但是,这不必要地为Vec<&str>
分配了内存。有更直接的方法吗?
答案 0 :(得分:2)
您可以使用 itertools 板条箱。在示例中,我使用了documentation帮助器,它几乎等同于 join 迭代器。
需要 cloned()
来将&&str
项转换为&str
项,它没有做任何分配。当copied()
获得稳定版本时,最终可以将其替换为rust@1.36
。
use itertools::Itertools; // 0.8.0
fn main() {
let words = ["alpha", "beta", "gamma"];
let merged: String = words.iter().cloned().intersperse(", ").collect();
assert_eq!(merged, "alpha, beta, gamma");
}
答案 1 :(得分:1)
您可以通过使用迭代器的fold
功能轻松做到这一点:
let s = it.fold(String::new(), |a, b| a + b + "\n");
完整代码如下:
fn main() {
let xs = vec!["first", "second", "third"];
let it = xs.into_iter();
// let s = it.collect::<Vec<&str>>().join("\n");
let s = it.fold(String::new(), |a, b| a + b + "\n");
let s = s.trim_end();
println!("{:?}", s);
}
编辑:在塞巴斯蒂安·雷德尔(Sebastian Redl)发表评论后,我检查了折叠使用的性能成本,并在运动场上创建了benchmark test。
您可以看到,fold
的使用对于许多迭代方法而言要花费更多的时间。
虽然没有检查分配的内存使用情况。
答案 2 :(得分:-1)
防锈文档中有相关示例:here。
let words = ["alpha", "beta", "gamma"];
// chars() returns an iterator
let merged: String = words.iter()
.flat_map(|s| s.chars())
.collect();
assert_eq!(merged, "alphabetagamma");
您还可以使用Extend
特征:
fn f<'a, I: Iterator<Item=&'a str>>(data: I) -> String {
let mut ret = String::new();
ret.extend(data);
ret
}