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
TypeErrorif 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
groupinstead.