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

countBy

Counts the number of occurrences of items in an array based on a key-generating function.

TypeScript
Copied!
1/**
2 * Counts the number of occurrences of items in an array based on a key-generating function.
3 *
4 * @param arr - The input array of values.
5 * @param fn - A callback that returns a key for each element.
6 * @returns An object with keys and their associated counts.
7 */
8export function countBy<T>(
9  arr: T[],
10  fn: (item: T) => string | number
11): Record<string, number> {
12  return arr.reduce((acc, item) => {
13    const key = String(fn(item));
14    acc[key] = (acc[key] || 0) + 1;
15    return acc;
16  }, {} as Record<string, number>);
17}
  • Flexible key extraction

    Supports a custom fn that determines how items are grouped and counted, enabling counting by any derived property (length, type, category, etc.).

  • Handles any data type

    Can process arrays of strings, numbers, objects, or mixed types, as long as a valid key can be extracted.

  • Efficient single-pass

    Uses a single reduce traversal to compute all counts, optimizing performance for large datasets.

  • String-key normalization

    Ensures compatibility by converting all keys to strings, preventing object key collisions or unexpected behavior.

  • Clear output structure

    Returns a plain object mapping keys to count values, ideal for use in reporting, analytics, or visualization.

Tests | Examples

TypeScript
Copied!
1test('countBy - count by string length', () => {
2  expect(countBy(['one', 'two', 'three'], x => x.length)).toEqual({ '3': 2, '5': 1 });
3});
4
5test('countBy - count by first letter', () => {
6  expect(countBy(['apple', 'apricot', 'banana', 'blueberry'], x => x[0]))
7    .toEqual({ a: 2, b: 2 });
8});
9
10test('countBy - numbers grouped by modulo', () => {
11  expect(countBy([1, 2, 3, 4, 5, 6], x => x % 2 === 0 ? 'even' : 'odd'))
12    .toEqual({ odd: 3, even: 3 });
13});
14
15test('countBy - empty array', () => {
16  expect(countBy([], x => x)).toEqual({});
17});

Common Use Cases

  • Analytics and metrics

    Counting categories, frequencies, or types within a dataset (e.g., number of users per role, product sales by category).

  • Text and log processing

    Tally word lengths, first letters, file extensions, or log severity levels.

  • Data grouping previews

    Generate counts to preview how many items would fall into each group before applying more expensive transformations.

  • Survey result summaries

    Count answer frequencies from a set of responses.

  • Dashboard aggregates

    Build quick count-based summaries in UI dashboards or tables.

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