Group Consecutive Elements In An Array By Condition In Ruby
Use chunk_while to group adjacent array elements that share a condition — perfect for run-length encoding, streak detection, and range grouping.
Description
Enumerable#chunk_while yields each consecutive pair (a, b) and groups elements into chunks as long as the block returns truthy. When the block returns false, a new chunk begins. It returns an Enumerator of arrays — each inner array is one group.
Common uses: grouping consecutive integers into ranges, grouping sorted dates into streaks, run-length encoding, and partitioning data by monotonic properties.
Sample input:
[1, 2, 3, 7, 8, 9, 15, 16]
Sample Output:
[[1, 2, 3], [7, 8, 9], [15, 16]]
Answer
arr = [1, 2, 3, 7, 8, 9, 15, 16]
# Group consecutive integers (differ by 1)
arr.chunk_while { |a, b| b == a + 1 }.to_a
# => [[1, 2, 3], [7, 8, 9], [15, 16]]
# Convert consecutive groups to ranges
arr.chunk_while { |a, b| b == a + 1 }
.map { |group| group.first..group.last }
# => [1..3, 7..9, 15..16]
# Group non-decreasing sequences
[3, 1, 4, 1, 5, 9, 2, 6].chunk_while { |a, b| b >= a }.to_a
# => [[3], [1, 4], [1, 5, 9], [2, 6]]
# Detect login streaks from sorted dates
dates = [Date.new(2024,1,1), Date.new(2024,1,2), Date.new(2024,1,4), Date.new(2024,1,5)]
streaks = dates.chunk_while { |a, b| (b - a).to_i == 1 }.to_a
# => [[2024-01-01, 2024-01-02], [2024-01-04, 2024-01-05]]
longest_streak = streaks.max_by(&:length)
Check viewARU - Brand Newsletter!
Newsletter to DEVs by DEVs - boost your Personal Brand & career! 🚀