UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

102 lines (101 loc) 3.55 kB
import { DeepMap } from './deepMap'; function DEFAULT_TO_KEY(value) { return value; } export function aggregate(aggregateParams, data) { const { groupBy = [], defaultToKey = DEFAULT_TO_KEY, reducers } = aggregateParams; const groupByLength = groupBy.length; const deepMap = new DeepMap(); let currentGroupKeys = []; const getInitialReducerValue = () => { return structuredClone(initReducers(reducers)); }; const globalReducerResults = getInitialReducerValue(); for (let i = 0, len = data.length; i < len; i++) { let item = data[i]; for (let groupByIndex = 0; groupByIndex < groupByLength; groupByIndex++) { const { field: groupByProperty, toKey: groupToKey } = groupBy[groupByIndex]; const key = (groupToKey || defaultToKey)(item[groupByProperty], item); currentGroupKeys.push(key); if (!deepMap.has(currentGroupKeys)) { const deepMapGroupValue = { items: [], reducerResults: getInitialReducerValue(), }; deepMap.set(currentGroupKeys, deepMapGroupValue); } const { items: currentGroupItems, reducerResults } = deepMap.get(currentGroupKeys); currentGroupItems.push(item); if (reducers) { computeReducersFor(item, reducers, reducerResults, i); } } if (reducers) { computeReducersFor(item, reducers, globalReducerResults, i); } currentGroupKeys.length = 0; } if (reducers) { deepMap.visitDepthFirst((deepMapValue, _keys, _indexInGroup, next) => { completeReducers(reducers, deepMapValue.reducerResults, deepMapValue.items); next?.(); }); } if (reducers) { completeReducers(reducers, globalReducerResults, data); } const result = { deepMap, aggregateParams, initialData: data, reducerResults: globalReducerResults, }; return result; } function initReducers(reducers) { if (!reducers || !Object.keys(reducers).length) { return {}; } const result = {}; for (let key in reducers) if (reducers.hasOwnProperty(key)) { result[key] = reducers[key].initialValue; } return result; } /** * * This fn mutates the reducerResults array!!! * * @param data data item * @param reducers an array of reducers * @param reducerResults the results on which to operate * */ function computeReducersFor(data, reducers, reducerResults, dataIndex) { if (!reducers || !Object.keys(reducers).length) { return; } for (let key in reducers) if (reducers.hasOwnProperty(key)) { const reducer = reducers[key]; if (typeof reducer.reducer !== 'function') { continue; } const currentValue = reducerResults[key]; const value = reducer.field ? data[reducer.field] : reducer.getter?.(data) ?? null; reducerResults[key] = reducer.reducer(currentValue, value, data, dataIndex); } } function completeReducers(reducers, reducerResults, items) { if (reducers) { for (let key in reducers) if (reducers.hasOwnProperty(key)) { const reducer = reducers[key]; if (reducer.done) { reducerResults[key] = reducer.done(reducerResults[key], items); } } } return reducerResults; }