Skip to content
VersionSize

aggregate

The aggregate utility transforms an array of objects into a single object, where each key is determined by a selector. If multiple items result in the same key, the last one processed "wins."

Implementation

View Source Code
ts
import { assert } from '../function/assert';
import { IS_ARRAY_ERROR_MSG, isArray } from '../typed/isArray';
import type { Selector } from '../types';

/**
 * Aggregates an array of objects into an object based on a key generated by a selector function.
 *
 * @example
 * ```ts
 * const data = [{ a: 1 }, { a: 2 }, { a: 1 }];
 * aggregate(data, 'a') // { '1': { a: 1 }, '2': { a: 2 } };
 * ```
 *
 * @param array - The array to key.
 * @param selector - The function to generate the key for each element. It can be a string representing the key or a function that returns the key.
 *
 * @returns An object with keys as the generated values and values as the last element responsible for generating the key.
 *
 * @throws {TypeError} If the provided array is not an array.
 */
export function aggregate<T, K extends keyof T, R extends T[K] extends string ? T[K] : never>(
  array: T[],
  selector: Selector<T>,
): Record<R, T> {
  assert(isArray(array), IS_ARRAY_ERROR_MSG, { args: { array }, type: TypeError });

  const result = {} as Record<R, T>;
  const getKey = typeof selector === 'function' ? selector : (item: T) => item[selector];

  for (const item of array) {
    const key = getKey(item) as R;

    result[key] = item;
  }

  return result;
}

aggregate.fp = true;

Features

  • Isomorphic: Works in both Browser and Node.js.
  • Flexible Keys: Use a property string or a custom function to generate keys.
  • Efficient Transformation: Quickly convert lists into lookup maps.

API

Type Definitions
ts
export type Selector<T> = keyof T | ((item: T) => Primitive);
ts
function aggregate<T, K extends keyof T, R extends T[K] extends string ? T[K] : never>(
  array: T[],
  selector: Selector<T>,
): Record<R, T>;

Parameters

  • array: The array of objects to aggregate.
  • selector: A property key string or a function that returns the key for each element.

Returns

  • An object with keys as generated values and values as the last matching element for each key.

Examples

Basic Aggregation by Property

ts
import { aggregate } from '@vielzeug/toolkit';

const data = [
  { id: 'u1', name: 'Alice' },
  { id: 'u2', name: 'Bob' },
  { id: 'u1', name: 'Alice Smith' }, // Duplicate ID
];

const byId = aggregate(data, 'id');
/*
{
  u1: { id: 'u1', name: 'Alice Smith' },
  u2: { id: 'u2', name: 'Bob' }
}
*/

Aggregation with a Selector Function

ts
import { aggregate } from '@vielzeug/toolkit';

const products = [
  { sku: 'APL', price: 1.5, category: 'fruit' },
  { sku: 'BAN', price: 0.8, category: 'fruit' },
  { sku: 'CHX', price: 5.0, category: 'meat' },
];

const byCategory = aggregate(products, (p) => p.category);
/*
{
  fruit: { sku: 'BAN', price: 0.8, category: 'fruit' },
  meat: { sku: 'CHX', price: 5.0, category: 'meat' }
}
*/

Implementation Notes

  • Throws TypeError if the first argument is not an array.
  • For conflicting keys, the last item in the array is preserved.
  • If you need to preserve all items for a given key, use group instead.

See Also

  • group: Group array elements into lists by key.
  • uniq: Remove duplicate elements from an array.
  • reduce: Perform custom aggregations.