Home
Map
iter ExamplesLoop over elements in a vector or array with iter. Modify elements in a loop with iter_mut.
Rust
This page was last reviewed on Apr 6, 2023.
Iter. In Rust programs, like programs in any language, we often need to loop or iterate over elements. Iter() is a helpful function that is used in for-loops in Rust.
By returning references, iter() protects the elements of the loop from being modified. This makes code more reliable as the loop will not fail in a mysterious way.
for
Iter example. Here we have a vector of 3 color strings. We then use a for-loop over the colors—we call iter() in the for-loop statement.
Result Each color is accessed and printed. We cannot modify the colors in the loop.
vec
fn main() { let colors = vec!["blue", "orange", "yellow"]; // Use iter over the vector. for color in colors.iter() { println!("{}", color); } }
blue orange yellow
Iter assign error. The iter() function returns an immutable reference to each element looped over. This means we cannot mutate the value behind the reference.
fn main() { let colors = vec!["blue", "orange", "yellow"]; // Iter returns immutable references so the elements cannot be changed. for color in colors.iter() { *color = "grey"; } }
error[E0594]: cannot assign to `*color`, which is behind a `&` reference
Iter_mut. Suppose we have an array or vector and want to change elements in it as we loop over them. The iter_mut function is helpful here as it returns mutable references.
Tip We assign the value 3 to all elements in the array. The array ends up with 10 values of 3 in it.
fn main() { let mut values = [0; 10]; // Set all elements in the array to 3. for value in values.iter_mut() { // Dereference and assign. *value = 3; } println!("{:?}", values); }
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
Into_iter. It is sometimes useful to call the into_iter function. With into_iter can avoid having references to elements in return values.
into iter
Tip Into_iter is often needed when using collect() to create a vector of the original element type.
collect
fn main() { let values = vec![1, 2, 3]; // Use into_iter to avoid references to elements and have usize elements. let result = values.into_iter().collect::<Vec<usize>>(); println!("{:?}", result); }
[1, 2, 3]
Enumerate. Once we call iter() on a vector or array, we can access the iterator methods. One common method to call is enumerate.
Info Enumerate returns the index and value for each element in an iterator.
fn main() { let colors = vec!["blue", "yellow", "green"]; // Use enumerate on iter() to access values and their indexes. for (i, color) in colors.iter().enumerate() { println!("{i} {color}"); } }
0 blue 1 yellow 2 green
Zip. With iter() and zip, we can loop over two vectors or arrays at once. The elements are returned as tuples (pairs). This can improve some loops that use iterators.
fn main() { let left = vec![1, 2, 3]; let right = vec![4, 5, 6]; // Use iter and zip to loop over both vectors at once. for pair in left.iter().zip(right) { println!("ZIP: {} {}", pair.0, pair.1); } }
ZIP: 1 4 ZIP: 2 5 ZIP: 3 6
Min and max. It is possible to use min() and max() on an iterator to get the smallest or largest values. An option is returned, so we must use unwrap or an if-let Some statement.
Tip If we use min() or max after calling iter() we will get a reference to the value. Using into_iter will give us values, not references.
fn main() { let values = [10, 5, 3, 20, 4]; // Use min and unwrap. let min = values.into_iter().min().unwrap(); // Use max. let max = values.into_iter().max().unwrap(); println!("MIN = {min}, MAX = {max}"); }
MIN = 3, MAX = 20
Iter performance. Is there any performance loss when using iter instead of a for range loop? In this benchmark we try to answer this question.
Version 1 We use a for-range loop over the indexes of the vector. We add up all the values in the vector repeatedly.
Version 2 Here we do the same thing as the previous loop, but we use the iter() function to access each element.
Result In release compilation, there is no performance loss associated with using iter. Iter() is a zero-cost abstraction in Rust.
use std::time::*; fn main() { let values = vec![1; 100000]; if let Ok(max) = "100000".parse::<usize>() { let mut count = 0; // Version 1: use range loop. let t0 = Instant::now(); for _ in 0..max { for i in 0..values.len() { count += values[i]; } } println!("{} ms", t0.elapsed().as_millis()); // Version 2: use iter. let t1 = Instant::now(); for _ in 0..max { for value in values.iter() { count += value; } } println!("{} ms", t1.elapsed().as_millis()); println!("{}", count); } }
839 ms 838 ms -1474836480
Summary. Using iter() and iter_mut() is often done in Rust programs. It can improve code reliability, as it will avoid programming bugs where values are modified in unexpected ways during looping.
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 Apr 6, 2023 (new example).
Home
Changes
© 2007-2024 Sam Allen.