#231 Jun 30, 2026

231. slice::chunk_by — Group Consecutive Elements Without the Index Bookkeeping

Splitting a slice into runs of equal (or related) elements usually means a manual loop with a start index and an off-by-one waiting to happen. slice::chunk_by does it in one call.

You want to break [1, 1, 2, 3, 3, 3, 1] into its runs of equal values. The hand-rolled version tracks where each run starts and has to remember to flush the last one:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let data = [1, 1, 2, 3, 3, 3, 1];

let mut groups: Vec<&[i32]> = Vec::new();
let mut start = 0;
for i in 1..=data.len() {
    if i == data.len() || data[i] != data[i - 1] {
        groups.push(&data[start..i]);
        start = i;
    }
}

chunk_by takes a predicate over consecutive pairs and starts a new chunk whenever it returns false:

1
2
3
4
5
6
7
8
let data = [1, 1, 2, 3, 3, 3, 1];

let groups: Vec<&[i32]> = data.chunk_by(|a, b| a == b).collect();

assert_eq!(
    groups,
    [&[1, 1][..], &[2], &[3, 3, 3], &[1]],
);

The predicate is any relation between neighbours, not just equality. Want the ascending runs of a sequence? Split where the order breaks:

1
2
3
4
5
let nums = [1, 3, 5, 2, 4, 1];

let runs: Vec<&[i32]> = nums.chunk_by(|a, b| a <= b).collect();

assert_eq!(runs, [&[1, 3, 5][..], &[2, 4], &[1]]);

Each chunk is a borrowed &[T] into the original slice — no copying. There’s a chunk_by_mut for when you need &mut [T] slices instead. (Stable since Rust 1.77; it was briefly named group_by.)

← Previous 230. slice::split_at_mut — Two Mutable Halves, No unsafe, No Borrow Fight