for each Example (iter chain)
This page was last reviewed on Mar 24, 2023.
Dot Net Perls
For each, chain. In Rust we often act upon iterators returned by the iter() function. We can use for_each to call code upon each element.
And with chain, we can elegantly combine two or more iterators. This lets us merge multiple loops into one, which can improve performance.
Example. Here we introduce increment_if_four—it receives a reference to a reference to string data. It increments the count argument if the length is 4.
String Length
Part 1 We create an array of string data (values) and call for_each and increment_if_four upon each element.
Part 2 We use chain() to merge together two arrays of string data. Then we call for_each and increment_if_four on these values.
fn increment_if_four(value: &&str, count: &mut usize) { // Increment mutable argument if string length is 4. if value.len() == 4 { *count += 1; } } fn main() { // Part 1: Use for_each function on iter. let count = &mut 0; let values = ["", "1234"]; values.iter().for_each(|x| increment_if_four(x, count)); println!("INCREMENT_IF_FOUR = {count}"); // Part 2: Use for_each with chain. let values2 = ["bird", "", "dog"]; let values3 = ["red", "blue"]; values2 .iter() .chain(values3.iter()) .for_each(|x| increment_if_four(x, count)); println!("INCREMENT_IF_FOUR = {count}"); }
Chain benchmark. With for_each and chain we can combine two loops into one. Occasionally this can perform faster than two loops in Rust programs.
Version 1 This version of the code uses 2 for-loops to iterate over the 2 arrays. It checks the length of each string.
Version 2 Here we use chain and for_each to combine the two loops into one. The counts are the same in both versions.
Result The version that uses chain and for_each to merge both loops is significantly faster.
use std::time::*; fn increment_if_four(value: &&str, count: &mut usize) { if value.len() == 4 { *count += 1; } } fn main() { let values1 = ["bird", "", "dog"]; let values2 = ["red", "blue", "?"]; if let Ok(max) = "100000000".parse::<usize>() { let count1 = &mut 0; let count2 = &mut 0; // Version 1: use 2 for-loops. let t0 = Instant::now(); for _ in 0..max { for value in values1.iter() { increment_if_four(&value, count1); } for value in values2.iter() { increment_if_four(&value, count1); } } println!("{} ms", t0.elapsed().as_millis()); // Version 2: use chain with for_each. let t1 = Instant::now(); for _ in 0..max { values1 .iter() .chain(values2.iter()) .for_each(|x| increment_if_four(x, count2)); } println!("{} ms", t1.elapsed().as_millis()); println!("{count1} = {count2}"); } }
476 ms for, for 16 ms chain, for_each 200000000 = 200000000
Chain notes. Suppose our Rust program has two collections (arrays or vectors), and we want to loop over both of them. With chain, we can just write one loop, with for_each.
And This can make our Rust program more elegant, and in some cases even faster.
String Array
A summary. Chain and for_each can often be used together. With for_each, we can modify a mutable argument, but we cannot return a value. This is useful in some programs.
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 Mar 24, 2023 (new example).
© 2007-2024 Sam Allen.