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

groupBy

Groups items in an array based on a key returned by a callback.

TypeScript
Copied!
1/**
2 * Groups items in an array based on a key returned by a callback.
3 *
4 * @param arr - The array to group.
5 * @param fn - A function that returns the key for grouping each item.
6 * @returns An object where each key maps to an array of grouped items.
7 */
8export function groupBy<T, K extends string | number>(
9  arr: T[],
10  fn: (item: T) => K
11): Record<K, T[]> {
12  return arr.reduce((acc, item) => {
13    const key = fn(item);
14    (acc[key] ||= []).push(item);
15    return acc;
16  }, {} as Record<K, T[]>);
17}
  • Flexible key selection

    Allows grouping by any derived key (e.g. user.id, item.category, str.length), enabling a wide range of grouping logic.

  • Single-pass efficiency

    Operates in a single reduce pass, giving it O(n) time complexity, which is optimal for this type of transformation.

  • Compact and immutable

    Returns a new grouped object without modifying the original array.

  • Type-safe with generics

    Leverages TypeScript’s generics for type inference of the key and grouped values, making it safer in large codebases.

  • Clean syntax using logical assignment

    (acc[key] ||= []) makes the grouping concise and readable without explicit checks.

Tests | Examples

TypeScript
Copied!
1test('groupBy - string length', () => {
2  const data = ['apple', 'banana', 'cherry'];
3  expect(groupBy(data, fruit => fruit.length)).toEqual({
4    5: ['apple'],
5    6: ['banana', 'cherry'],
6  });
7});
8
9test('groupBy - objects by field', () => {
10  const users = [
11    { name: 'Alice', role: 'admin' },
12    { name: 'Bob', role: 'user' },
13    { name: 'Eve', role: 'admin' },
14  ];
15  expect(groupBy(users, user => user.role)).toEqual({
16    admin: [
17      { name: 'Alice', role: 'admin' },
18      { name: 'Eve', role: 'admin' },
19    ],
20    user: [
21      { name: 'Bob', role: 'user' },
22    ],
23  });
24});
25
26test('groupBy - empty array', () => {
27  expect(groupBy([], x => x)).toEqual({});
28});

Common Use Cases

  • UI grouping (e.g. lists, dropdowns, tables)

    Grouping items by status, category, tag, author, etc., for rendering in sections or filters.

  • Data analysis and aggregation

    Binning raw data by metric or dimension (e.g., count by year, events per user, tasks per project).

  • Pre-processing for charts/visualizations

    Organizing datasets into categories or series before rendering bar/line/pie charts.

  • Log/event processing

    Bucket events by date, severity, or type for further processing or alerting.

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