Join iterator of &str
Solution 1
You could use the itertools crate for that. I use the intersperse helper in the example, it is pretty much the join equivalent for iterators.
cloned()
is needed to convert &&str
items to &str
items, it is not doing any allocations. It can be eventually replaced by copied()
when [email protected]
gets a stable release.
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");
}
Solution 2
You can do it by using fold
function of the iterator easily:
let s = it.fold(String::new(), |a, b| a + b + "\n");
The Full Code will be like following:
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);
}
EDIT: After the comment of Sebastian Redl I have checked the performance cost of the fold usage and created a benchmark test on playground.
You can see that fold
usage takes significantly more time for the many iterative approaches.
Did not check the allocated memory usage though.
Mateen Ulhaq
Elen síla lúmenn' omentielvo. Favorite languages: Python, Rust, Kotlin, C++, C#, Haskell Photography
Updated on June 06, 2022Comments
-
Mateen Ulhaq almost 2 years
What is the canonical method to convert an
Iterator<&str>
to aString
, interspersed with some constant string (e.g."\n"
)?For instance, given:
let xs = vec!["first", "second", "third"]; let it = xs.iter();
There is a way to produce a string
s
by collecting into someIterable
andjoin
ing the result:let s = it .map(|&x| x) .collect::<Vec<&str>>() .join("\n");
However, this unnecessarily allocates memory for a
Vec<&str>
. Is there a more direct method?