| name | rust-iterators |
| description | Leverage iterator chains for efficient, lazy data processing without intermediate allocations. Use when processing collections. |
Iterator Patterns
Efficient data processing with lazy iterator chains.
Basic Iterator Chain
let result: Vec<_> = data
.iter()
.filter(|&&x| x > 2)
.map(|&x| x * 2)
.collect();
let sum: i32 = data.iter().filter(|&&x| x > 0).sum();
let count = data.iter().filter(|x| x.is_valid()).count();
Common Iterator Methods
.map(|x| transform(x))
.filter(|x| predicate(x))
.filter_map(|x| x.ok())
.flat_map(|x| x.into_iter())
.take(10)
.skip(5)
.take_while(|x| x < &100)
.skip_while(|x| x < &10)
.find(|x| predicate(x))
.position(|x| predicate(x))
.any(|x| predicate(x))
.all(|x| predicate(x))
.fold(0, |acc, x| acc + x)
.reduce(|a, b| a + b)
.sum::<i32>()
.product::<i32>()
.collect::<Vec<_>>()
.collect::<HashSet<_>>()
.collect::<String>()
.collect::<Result<Vec<_>, _>>()
Parallel Iteration with Rayon
use rayon::prelude::*;
let sum: i32 = data.par_iter().map(|x| expensive(x)).sum();
let mut data = data;
data.par_sort();
let results: Vec<_> = data
.par_iter()
.filter(|x| predicate(x))
.map(|x| transform(x))
.collect();
Enumerate and Zip
for (index, item) in items.iter().enumerate() {
println!("{}: {}", index, item);
}
let pairs: Vec<_> = keys.iter().zip(values.iter()).collect();
let (keys, values): (Vec<_>, Vec<_>) = pairs.into_iter().unzip();
Chain and Flatten
let combined: Vec<_> = first.iter()
.chain(second.iter())
.chain(third.iter())
.collect();
let flat: Vec<_> = nested_vecs.iter().flatten().collect();
let all_items: Vec<_> = containers
.iter()
.flat_map(|c| c.items())
.collect();
Peekable Iterator
let mut iter = data.iter().peekable();
while let Some(¤t) = iter.next() {
if let Some(&&next) = iter.peek() {
if next > current {
}
}
}
Windows and Chunks
for window in data.windows(3) {
let [a, b, c] = window else { continue };
}
for chunk in data.chunks(100) {
process_batch(chunk);
}
for chunk in data.chunks_exact(100) {
process_batch(chunk);
}
Custom Iterator
struct Counter {
current: usize,
max: usize,
}
impl Iterator for Counter {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.current < self.max {
let result = self.current;
self.current += 1;
Some(result)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.max - self.current;
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for Counter {}
Collect into Result
let results: Result<Vec<_>, _> = items
.iter()
.map(|item| fallible_operation(item))
.collect();
match results {
Ok(values) => process(values),
Err(e) => handle_error(e),
}
Performance Tips
let temp: Vec<_> = data.iter().filter(|x| x > &0).collect();
let result: i32 = temp.iter().sum();
let result: i32 = data.iter().filter(|&&x| x > 0).sum();
let mut sum = 0;
for x in &data {
if *x > 0 {
sum += x;
}
}
let sum: i32 = data.iter().filter(|&&x| x > 0).sum();
Guidelines
- Prefer iterator chains over manual loops
- Avoid collecting intermediate results
- Use
filter_map to combine filter + map for Options
- Use
flat_map to flatten nested structures
- Use Rayon for CPU-bound parallel work
- Implement
size_hint for custom iterators
- Use
chunks for batch processing
Examples
See hercules-local-algo/src/pipeline/ for iterator patterns.