Loop over chars. Whenever we need to use strings in Rust, we usually will need to loop over their chars and modify them in some way. Rust provides iterators over strings.
For-in loop. With a for-in loop, we can use an iterator with minimal syntax to loop over a string. We can use the loop to create a new string, or perform other logic.
First example. To begin, we have a simple string that contains the word "abc." We call chars() to get an iterator of all the characters in this string.
Detail We use a for-in loop directly on the iterator returned by chars. Each time the loop executes, the variable is set to a character.
fn main() {
let test = "abc";
// Get chars.
let values = test.chars();
// Use for-in loop to print all chars.
for c in values {
println!("CHARACTER: {}", c)
}
}CHARACTER: a
CHARACTER: b
CHARACTER: c
Reverse loop. We can change how the iterator returned by chars() loops over characters. With rev(), for example, we can loop over the chars in reverse order.
fn main() {
let test = "cat";
// Loop over chars backwards.
for c in test.chars().rev() {
println!("REV: {}", c)
}
}REV: t
REV: a
REV: c
Bytes. Suppose we have an ASCII-only string, and want to get each byte in a loop. The bytes() function is ideal here. It returns a u8 on each iteration.
fn print_bytes(value: &str) {
// Loop over bytes.
for b in value.bytes() {
println!("BYTE: {b}");
}
}
fn main() {
print_bytes("rust");
}BYTE: 114
BYTE: 117
BYTE: 115
BYTE: 116
Char vec. Suppose we want to access each character in a string by its index. We may want to access other indexes at the same time. We can convert a string to a Vector.
And We can then loop over the indexes of the vector, accessing each char. We can access adjacent chars at different indexes in the same loop.
fn main() {
let name = "cat";
let letters = name.chars().collect::<Vec<char>>();
// Loop over characters by index.// We can access other indexes more easily this way.
for i in 0..letters.len() {
println!("{}", letters[i]);
}
}c
a
t
Chars, bytes benchmark. Suppose we have a string we know is only ASCII. Should we use chars() or bytes() to iterate over the string?
Version 1 This version of the code uses the chars() function to access each char in the string. It tests for the letter "e".
Version 2 This code does the same thing as version 1, but uses the bytes() function to handle bytes.
Result Using bytes() is almost twice as fast as using chars. If a string is only ASCII, bytes() should be considered.
use std::time::*;
fn main() {
let mut example = String::new();
example.push_str("yellow bird ");
example.push_str("and green frog");
// Version 1: use chars.
let t0 = Instant::now();
let mut count = 0;
for _ in 0..1000000 {
for c in example.chars() {
if c == 'e' {
count += 1;
}
}
}
println!("{}", t0.elapsed().as_millis());
// Version 2: use bytes.
let t1 = Instant::now();
let mut count2 = 0;
for _ in 0..1000000 {
for b in example.bytes() {
if b == b'e' {
count2 += 1;
}
}
}
println!("{}", t1.elapsed().as_millis());
println!("{count} {count2}");
}20 ms (chars)
11 ms (bytes)
3000000 3000000
A review. We cannot directly access the chars in a string, as each char may be a different size. But with iterators, we can loop over and test each char in order.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Feb 12, 2023 (new example).