export type GroupByKeysIn = { [keyName: string]: T }; export type GroupByKeysOut = { [keyName: string]: T[] }; /** * group item's values by it's key * eg: * ```js * const from = [ * { a: 1, b: [ 'z' ] }, * { a: 2, b: [ 'z' ] }, * { a: [ 3, 4 ] } * ] * to = groupByKeys(from); * to === { * a: [ 1, 2, 3, 4], * b: [ 'z', 'z' ] * } * ``` */ export function groupByKeys(items: GroupByKeysIn[]): GroupByKeysOut { return items.reduce((sum: { [categoryName: string]: any[] }, x) => { for(const [ keyName, value ] of Object.entries(x)) { if (!(keyName in sum)) sum[keyName] = []; if (Array.isArray(value)) sum[keyName].push(...value); else sum[keyName].push(value); }; return sum; }, {}); } /** * ```js * { * x: [ * { a: 1, b: 2 }, * { a: 3, b: 4 } * ], * y: [ * { a: 5, b: 6 }, * { a: 7, b: 8 } * ] * } * // to * { * x: { * a: [ 1, 3 ], * b: [ 2 , 4 ] * } * y: { * a: [ 5, 7 ], * b: [ 6 , 8 ] * } * } * ``` */ export function groupEveryKeyByKeys(item: { [key: string]: GroupByKeysIn[] }): { [key: string]: GroupByKeysOut } { return Object.entries(item).reduce((sum, [ key, value ]) => Object.assign(sum, { [key]: groupByKeys(value) }), {}); }