rust &str的联接迭代器

bhmjp9jg  于 2023-04-30  发布在  其他
关注(0)|答案(3)|浏览(241)

如何将Iterator<&str>转换为String,并插入一个常量字符串,如"\n"?例如,给定:

let xs = vec!["first", "second", "third"];
let it = xs.iter();

我们可以通过collecting生成一个Vec<&str>joining结果来生成一个字符串s

let s = it
    .map(|&x| x)
    .collect::<Vec<&str>>()
    .join("\n");

但是,这不必要地为Vec<&str>分配内存
有没有更直接的方法?

rryofs0p

rryofs0p1#

你可以使用 itertools crate来实现。我在示例中使用了 intersperse 帮助器,它几乎等同于迭代器的 join
cloned()需要将&&str项转换为&str项,但它不执行任何分配。当rust@1.36获得稳定版本时,它最终可以被copied()取代。

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");
}

Playground

yhived7q

yhived7q2#

你可以通过使用迭代器的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);
}

Playground
编辑:在塞巴斯蒂安Redl的评论之后,我检查了折叠使用的性能成本,并在操场上创建了一个benchmark test
您可以看到,对于许多迭代方法,fold的使用要花费更多的时间。

  • 但未检查分配的内存使用情况 *。
disbfnqx

disbfnqx3#

rust文档中有相关的例子:给你。

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 trait:

fn f<'a, I: Iterator<Item=&'a str>>(data: I) -> String {
    let mut ret = String::new();
    ret.extend(data);
    ret
}

相关问题