Since a string supports iteration but not indexing, I would like to convert a string into a list of chars. I have "abc"
and I want ['a', 'b', 'c']
.
It can be any type as long as I can index into it. A Vec<char>
or a [char; 3]
would be fine, other ideas would also be interesting!
Faster would be better since I am dealing with very long strings. A version that is more efficient when assuming that the string is ASCII would also be cool.
Use the chars
method on String
or str
:
fn main() {
let s = "Hello world!";
let char_vec: Vec<char> = s.chars().collect();
for c in char_vec {
println!("{}", c);
}
}
Here you have a live example
I've already come to this solution:
let chars: Vec<char> = input.chars().collect();
In a comment somebody suggested using .split("")
but it seems to be implemented in a way that is annoying for this case:
println!("{:?}", "abc".split("").collect::<Vec<&str>>());
gives ["", "a", "b", "c", ""]
Since you are trying to solve the first day of Advent of Code, I'm assuming that you need to compare two consecutive characters and update an accumulator depending on whether the characters are the same. You can do that without indexing by using the fold
function on chars
. Something like this (untested):
fn example(s: &str) -> u32 {
let mut i = s.chars()
.map(|c| c.to_digit(10).expect("Invalid input: Non-digit found!"));
if let Some(first) = i.next() {
let (tot, last) = i.fold((0, first), |acc, x| {
let (tot, prev) = acc;
if prev == x {
(tot + prev, x)
} else {
(tot, x)
}
});
if last == first {
tot + last
} else {
tot
}
} else {
0
}
}
The fold
iterator method allows you to walk a value over all the iterator items updating that value at each step. Here the value is a tuple containing the accumulated result and the value of the previous digit. We initialize it with some initial result and the value of the first character. Then at each step we compare the current character with the previous one taken from the current value, update the accumulated result depending on the result of the comparison and return a new value with the updated accumulator and the current character.
The fold
method returns the last value, which in our case contains the accumulated result and the last character, at which point you may check if the last character is the same as the first one and update the result if you need to.