How to split string into chunks in Rust to insert spaces
If the size of the data you want to split in is fixed then:
use std::str;
fn main() {
let subs = "‌​‌​‌​​‌​‌".as_bytes()
.chunks(7)
.map(str::from_utf8)
.collect::<Result<Vec<&str>, _>>()
.unwrap();
println!("{:?}", subs);
}
// >> ["‌", "​", "‌", "​", "‌", "​", "​", "‌", "​", "‌"]
So if you want to work from a list of chars to create a String, you can use fold for that.
Something like this :
text.chars
.enumerate()
.fold(String::new(), |acc, (i, c)| {
if i != 0 && i == n {
format!("{} {}", acc, c)
} else {
format!("{}{}", acc, c)
}
})
Such a simple task can be solved with a single loop:
fn main() {
let n = 4;
let text = "whatupmyname";
let mut result = String::new();
for (i, c) in text.chars().enumerate() {
result.push(c);
if (i + 1) % n == 0 {
result.push(' ');
}
}
println!("{:?}", result); // "what upmy name "
}
The problem here is that chars()
and bytes()
return Iterator
s, not slices. You could use as_bytes()
, which will give you a &[u8]
. However, you cannot directly get a &[char]
from a &str
, because there only exists the bytes themselves, and the char
s must be created by looking through and seeing how many bytes makes up each one. You'd have to do something like this:
text.chars()
.collect::<Vec<char>>()
.chunks(n)
.map(|c| c.iter().collect::<String>())
.collect::<Vec<String>>()
.join(" ");
However, I would NOT recommend this as it has to allocate a lot of temporary storage for Vec
s and String
s along the way. Instead, you could do something like this, which only has to allocate to create the final String
.
text.chars()
.enumerate()
.flat_map(|(i, c)| {
if i != 0 && i % n == 0 {
Some(' ')
} else {
None
}
.into_iter()
.chain(std::iter::once(c))
})
.collect::<String>()
This stays as iterators until the last collect, by flat_mapping with an iterator that is either just the character or a space and then the character.