Use windows() to iterate over overlapping sub-slices of a fixed size, and chunks() to iterate over non-overlapping sub-slices of a fixed size. Both methods return an iterator that yields &[T] references, allowing you to process data in batches without copying or managing indices manually.
Here is how to apply them in practice:
fn main() {
let data = [1, 2, 3, 4, 5, 6];
// windows(3) creates overlapping views: [1,2,3], [2,3,4], [3,4,5], [4,5,6]
for window in data.windows(3) {
println!("Window sum: {}", window.iter().sum::<i32>());
}
// chunks(3) creates non-overlapping views: [1,2,3], [4,5,6]
for chunk in data.chunks(3) {
println!("Chunk product: {}", chunk.iter().product::<i32>());
}
// chunks_exact(3) is stricter: it ignores the last element if the slice length
// isn't a multiple of the chunk size (unlike chunks which yields a smaller final chunk)
for exact in data.chunks_exact(3) {
println!("Exact chunk: {:?}", exact);
}
}
Key differences to remember: windows(n) produces len - n + 1 items and is ideal for sliding window algorithms like moving averages or pattern matching. chunks(n) produces ceil(len / n) items and is best for batch processing where you want to handle data in fixed-size groups. If you need to ensure every yielded slice is exactly size n and don't care about leftover data, use chunks_exact(n) instead of chunks(n).
Both methods work on any slice type (&[T]) and are zero-cost abstractions that compile down to efficient loops. They are particularly useful when combined with iterator adapters like map, filter, or fold to transform or aggregate data streams.