mirror of
https://github.com/denoland/std.git
synced 2024-11-22 04:59:05 +00:00
d102a10235
* refactor: import from `@std/assert` * update
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
// This module is browser compatible.
|
|
|
|
import { mapEntries } from "./map_entries.ts";
|
|
|
|
/**
|
|
* Applies the given aggregator to each group in the given grouping, returning the
|
|
* results together with the respective group keys
|
|
*
|
|
* @typeParam T Type of the values in the input record.
|
|
* @typeParam A Type of the accumulator value, which will match the returned
|
|
* record's values.
|
|
*
|
|
* @param record The grouping to aggregate.
|
|
* @param aggregator The function to apply to each group.
|
|
*
|
|
* @returns A record with the same keys as the input record, but with the values
|
|
* being the result of applying the aggregator to each group.
|
|
*
|
|
* @example Basic usage
|
|
* ```ts
|
|
* import { aggregateGroups } from "@std/collections/aggregate-groups";
|
|
* import { assertEquals } from "@std/assert";
|
|
*
|
|
* const foodProperties = {
|
|
* Curry: ["spicy", "vegan"],
|
|
* Omelette: ["creamy", "vegetarian"],
|
|
* };
|
|
*
|
|
* const descriptions = aggregateGroups(
|
|
* foodProperties,
|
|
* (current, key, first, acc) => {
|
|
* return first
|
|
* ? `${key} is ${current}`
|
|
* : `${acc} and ${current}`;
|
|
* },
|
|
* );
|
|
*
|
|
* assertEquals(descriptions, {
|
|
* Curry: "Curry is spicy and vegan",
|
|
* Omelette: "Omelette is creamy and vegetarian",
|
|
* });
|
|
* ```
|
|
*/
|
|
export function aggregateGroups<T, A>(
|
|
record: Readonly<Record<string, ReadonlyArray<T>>>,
|
|
aggregator: (current: T, key: string, first: boolean, accumulator?: A) => A,
|
|
): Record<string, A> {
|
|
return mapEntries(
|
|
record,
|
|
([key, values]) => [
|
|
key,
|
|
// Need the type assertions here because the reduce type does not support
|
|
// the type transition we need
|
|
values.reduce(
|
|
(accumulator, current, currentIndex) =>
|
|
aggregator(current, key, currentIndex === 0, accumulator),
|
|
undefined as A | undefined,
|
|
) as A,
|
|
],
|
|
);
|
|
}
|