/** @module array/groupBy.ts */ import { untypedCurry } from '../function/untypedCurry' import { Maybe } from '../maybe' import { safeProp } from '../maybe-functions' import { assign } from '../object' import { fromSinglePair } from '../pairs/fromSinglePair' const _appendToProp = ( item, key, acc ) => ( safeProp( key, acc ) as Maybe ) .map( ( groupXs: A[] ) => groupXs.concat( item ) ) .joinOrValue( [ item ] ) // tslint:disable-next-line:variable-name const _groupBy = untypedCurry( ( fn: ( A ) => string, list: A[] ) => { return list.reduce( ( acc, item: A ) => assign( acc, Maybe.of( fn( item ) ) .map( ( key ) => fromSinglePair( key, _appendToProp( item, key, acc ) ) ) .joinOrValue( {} ) ), {} ) } ) export function groupBy( fn: ( a: T ) => K, arr: ReadonlyArray ): Record export function groupBy( fn: ( a: T ) => K ): ( arr: ReadonlyArray ) => Record /** * Group items in an array `arr` per returned string values in function `fn` * @param fn function takes value T from array T[] returning a string * @param arr an array of T[] * @sig ( a -> str ) -> a[] -> { str1 : a1, str2: a2, ... } * @example * groupBy( x => x % 2 ? 'odd' : 'even', [1,2,3,4,5,6,7]) * // { odd: [ 1, 3, 5, 7 ], even: [ 2, 4, 6 ] } : Record< 'odd' | 'even', number[]> */ export function groupBy( ...args ) { return _groupBy( ...args ) } const fff = groupBy( ( x ) => x % 2 ? 'odd' : 'even', [ 1, 2, 3, 4, 5, 6, 7 ] )