Iterators in Depth
Iterators are central to idiomatic Rust. The Iterator trait provides dozens of adapters that compose into powerful, zero-cost data processing pipelines.
fn main() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Core operations
let sum: i32 = v.iter().sum();
let product: i32 = v.iter().product();
let max = v.iter().max();
let count = v.iter().count();
println!("sum={} product={} max={:?} count={}", sum, product, max, count);
// map: transform each element
let doubled: Vec = v.iter().map(|&x| x * 2).collect();
// filter: keep matching elements
let evens: Vec<&i32> = v.iter().filter(|&&x| x % 2 == 0).collect();
// filter_map: filter AND transform in one step
let strs = vec!["1", "two", "3", "four", "5"];
let nums: Vec = strs.iter().filter_map(|s| s.parse().ok()).collect();
println!("{:?}", nums); // [1, 3, 5]
// fold: reduce to a single value
let sum2 = v.iter().fold(0, |acc, &x| acc + x);
// any / all
println!("{}", v.iter().any(|&x| x > 9)); // true
println!("{}", v.iter().all(|&x| x > 0)); // true
// find / position
println!("{:?}", v.iter().find(|&&x| x > 5)); // Some(&6)
println!("{:?}", v.iter().position(|&x| x == 5)); // Some(4)
// Chain multiple operations (zero-cost at runtime!)
let result: Vec = (1..=20)
.filter(|x| x % 3 == 0)
.map(|x| x * x)
.take(4)
.map(|x| format!("{}", x))
.collect();
println!("{:?}", result); // ["9", "36", "81", "144"]
} 🎯 Practice
- Use a single iterator chain to: take a Vec<String>, filter non-empty, trim each, collect into Vec<String>
- Use fold to compute standard deviation of a Vec<f64>
- Use filter_map to parse a Vec<&str> of "key=value" pairs into Vec<(&str, &str)>
🎉 Key Takeaways
- Iterators are lazy - no work done until consumed (collect, sum, for loop, etc.)
- Chains compile to efficient loops - no intermediate allocations
- filter_map combines filter and map - use when transformation can fail
- fold is the general reducer; sum, product, count, any, all are specialized