Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

chunkByPredicate

Splits an array into chunks whenever the predicate returns true. The chunk boundary is placed before the element where the predicate succeeds. The predicate is applied to each element (excluding the first).

TypeScript
Copied!
1/**
2 * Splits an array into chunks whenever the predicate returns true.
3 * The chunk boundary is placed before the element where the predicate succeeds.
4 * The predicate is applied to each element (excluding the first).
5 *
6 * @param arr - The array to split.
7 * @param predicate - A function that determines if a new chunk should start.
8 * @returns An array of chunked arrays.
9 */
10export function chunkByPredicate<T>(
11  arr: T[],
12  predicate: (current: T, index: number, array: T[]) => boolean
13): T[][] {
14  if (!arr.length) return [];
15
16  const result: T[][] = [];
17  let currentChunk: T[] = [arr[0]];
18
19  for (let i = 1; i < arr.length; i++) {
20    if (predicate(arr[i], i, arr)) {
21      result.push(currentChunk);
22      currentChunk = [arr[i]];
23    } else {
24      currentChunk.push(arr[i]);
25    }
26  }
27
28  result.push(currentChunk);
29  return result;
30}
  • Dynamic chunk boundaries

    Unlike fixed-size chunking, this utility allows intelligent and flexible splitting based on contextual logic (e.g., value thresholds, type changes, time gaps).

  • Fine-grained control

    The predicate receives current, index, and the entire array, enabling advanced splitting strategies that can react to complex patterns in data.

  • Efficient single pass

    Processes the array in a single iteration, keeping the runtime efficient even for large datasets.

  • Non-destructive

    Does not mutate the original array, ensuring safety when used in functional programming pipelines.

  • Robust against empty input

    Gracefully handles empty arrays by returning an empty result without throwing errors.

Tests | Examples

TypeScript
Copied!
1test('chunkByPredicate - chunks on even numbers', () => {
2  const input = [1, 3, 5, 2, 7, 2, 4];
3  const output = chunkByPredicate(input, x => x % 2 === 0);
4  expect(output).toEqual([[1, 3, 5], [2, 7], [2], [4]]);
5});
6
7test('chunkByPredicate - splits on negative numbers', () => {
8  const input = [10, 20, -1, 30, -2, 40];
9  const output = chunkByPredicate(input, x => x < 0);
10  expect(output).toEqual([[10, 20], [-1, 30], [-2, 40]]);
11});
12
13test('chunkByPredicate - empty array', () => {
14  expect(chunkByPredicate([], () => true)).toEqual([]);
15});
16
17test('chunkByPredicate - no predicate match', () => {
18  expect(chunkByPredicate([1, 2, 3], () => false)).toEqual([[1, 2, 3]]);
19});
20
21test('chunkByPredicate - predicate always true', () => {
22  expect(chunkByPredicate([1, 2, 3], () => true)).toEqual([[1], [2], [3]]);
23});

Common Use Cases

  • Log grouping or message segmentation

    Useful for splitting logs or event sequences whenever a special entry or delimiter appears (e.g., chunkByPredicate(logs, l => l.level === 'ERROR')).

  • Data stream segmentation

    For real-time systems, can group incoming packets/frames until a marker or reset flag is encountered.

  • Form input parsing

    Helps split dynamic multi-line input or CSV-like data whenever a specific token appears (e.g., empty string or linebreak).

  • Sectioning UI data

    Can split UI-rendered items (e.g., transactions, posts, measurements) into sections like "Today", "Yesterday", "Older", based on timestamp gaps.

  • Conditional batching

    Enables chunking for threshold-based or grouped processing, e.g., new chunk starts every time a value exceeds 100.

Codebase: Utilities -> Arrays -> chunkByPredicate | Yevhen Klymentiev