From e32de12346f089c0126cd732b3fc3365159f1229 Mon Sep 17 00:00:00 2001 From: Niles Turner Date: Sun, 29 Jan 2017 20:13:12 -0500 Subject: [PATCH] add aggregation types average, min and max --- lib/quick-pivot.js | 120 ++++++++++++++++++++++++++++----------------- test/logic.spec.js | 15 ++++++ 2 files changed, 89 insertions(+), 46 deletions(-) diff --git a/lib/quick-pivot.js b/lib/quick-pivot.js index 28e14c4..6154687 100644 --- a/lib/quick-pivot.js +++ b/lib/quick-pivot.js @@ -55,7 +55,7 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports, __webpack_require__) { 'use strict'; - + module.exports = __webpack_require__(1); /***/ }, @@ -63,11 +63,11 @@ return /******/ (function(modules) { // webpackBootstrap /***/ function(module, exports) { 'use strict'; - + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - + function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - + function fixDataFormat(data) { if (!Array.isArray(data) || !data.length) return [];else if (_typeof(data[0]) === 'object' && !Array.isArray(data[0])) return data; return data.reduce(function (dataCol, row, i, arr) { @@ -84,67 +84,67 @@ return /******/ (function(modules) { // webpackBootstrap return dataCol; }, []); } - + function groupByCategory(data, groupBy) { return data.reduce(function (acc, curr) { var category = curr[groupBy]; - + if (!acc[category]) acc[category] = []; acc[category].push(curr); return acc; }, {}); } - + function groupByCategories(data) { var groups = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var acc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - + if (!data.length) return []; - + groups = groups.filter(function (ele) { return ele in data[0]; }); - + if (!groups.length) return data; - + var groupCopy = Object.assign([], groups); var groupedData = groupByCategory(data, groupCopy.shift()); var groupedDataKeys = Object.keys(groupedData); var children = groupedDataKeys.map(function (el) { return groupedData[el]; }); - + for (var i = 0; i < children.length; i++) { acc[groupedDataKeys[i]] = groupCopy.length ? {} : []; acc[groupedDataKeys[i]] = groupByCategories(children[i], groupCopy, acc[groupedDataKeys[i]]); } - + return acc; } - + function createColumnHeaders(data) { var cols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var firstColumn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; - + if (!cols.length) return { columnHeaders: [firstColumn], mapToHeader: 1 }; - + var groupedData = groupByCategories(data, cols); var columnHeaders = []; var mapToHeader = Object.assign({}, groupedData); var mapPos = 1; - + (function columnHeaderRecursion(data) { var pos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var headerMap = arguments[2]; - + if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) !== 'object' || Array.isArray(data)) return 1; - + var currKeys = Object.keys(data); var reqLength = 0; - + for (var i = 0; i < currKeys.length; i++) { var currLength = columnHeaderRecursion(data[currKeys[i]], pos + 1, headerMap[currKeys[i]]); - + if (Array.isArray(data[currKeys[i]])) { headerMap[currKeys[i]] = mapPos; mapPos += 1; @@ -154,13 +154,13 @@ return /******/ (function(modules) { // webpackBootstrap } return reqLength; })(groupedData, 0, mapToHeader); - + return { columnHeaders: columnHeaders, mapToHeader: mapToHeader }; } - + /** * accumulator has two different signatures * 1. it takes an array of objects, an accumulation category as a string @@ -173,7 +173,7 @@ return /******/ (function(modules) { // webpackBootstrap accValue = accType || 0; accType = accCat; } - + return arr.reduce(function (acc, curr, index, array) { if (typeof accType === 'function') { return accType(acc, typeof accCat === 'string' ? curr[accCat] : curr, index, array); @@ -184,13 +184,41 @@ return /******/ (function(modules) { // webpackBootstrap acc += Number(curr[accCat]); return acc; } - + case 'count': { acc += 1; return acc; } - + + case 'average': + { + acc += Number(curr[accCat]) / arr.length; + return acc; + } + + case 'min': + { + if(index === 0) { + acc = Number(curr[accCat]) + } + else if (curr[accCat] < acc) { + acc = Number(curr[accCat]) + } + return acc; + } + + case 'max': + { + if(index === 0) { + acc = Number(curr[accCat]) + } + else if (curr[accCat] > acc) { + acc = Number(curr[accCat]) + } + return acc; + } + default: { acc += 1; @@ -199,10 +227,10 @@ return /******/ (function(modules) { // webpackBootstrap } }, accValue || 0); } - + function checkPivotCategories(actualCats, selectedCats) { var errMessage = []; - + selectedCats.forEach(function (selectedCat) { if (actualCats.indexOf(selectedCat) === -1) errMessage.push(selectedCat); }); @@ -210,55 +238,55 @@ return /******/ (function(modules) { // webpackBootstrap throw new Error('Check that these selected pivot categories exist: ' + errMessage.join(',')); } } - + function tableCreator(data) { var rows = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var cols = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var accCatOrCB = arguments[3]; var accTypeOrInitVal = arguments[4]; var rowHeader = arguments[5]; - + data = fixDataFormat(data); if (!data.length) return []; checkPivotCategories(Object.keys(data[0]), rows); checkPivotCategories(Object.keys(data[0]), cols); - + if (typeof rowHeader === 'undefined') { rowHeader = typeof accCatOrCB !== 'function' ? accTypeOrInitVal + ' ' + accCatOrCB : 'Custom Agg'; } - + var columnData = createColumnHeaders(data, cols, rowHeader); var columnHeaders = Array.isArray(columnData.columnHeaders[0]) ? columnData.columnHeaders : [columnData.columnHeaders.concat(rowHeader)]; var mapToHeader = columnData.mapToHeader; var headerLength = columnHeaders[0].length; - + var dataRows = []; var rawData = []; var prevKey = ''; - + function rowRecurse(rowGroups) { var _loop = function _loop(key) { if (Array.isArray(rowGroups[key])) { recursedData = groupByCategories(rowGroups[key], cols); - - + + (function recurseThroughMap(dataPos, map) { if (Array.isArray(dataPos)) { if (key === prevKey) { var datum = dataRows[dataRows.length - 1]; - + datum[map] = accumulator(dataPos, accCatOrCB, accTypeOrInitVal); dataRows[dataRows.length - 1] = datum; - + var rawDataDatum = rawData[rawData.length - 1]; - + rawDataDatum[map] = dataPos; rawData[rawData.length - 1] = rawDataDatum; } else { prevKey = key; var _datum = [key].concat(Array(map - 1).fill(''), accumulator(dataPos, accCatOrCB, accTypeOrInitVal), Array(headerLength - (map + 1)).fill('')); var _rawDataDatum = [key].concat(Array(map - 1).fill(''), [dataPos], Array(headerLength - (map + 1)).fill('')); - + rawData.push(_rawDataDatum); dataRows.push(_datum); } @@ -273,27 +301,27 @@ return /******/ (function(modules) { // webpackBootstrap rowRecurse(rowGroups[key], key); } }; - + for (var key in rowGroups) { var recursedData; - + _loop(key); } } - + if (rows.length || cols.length) { rowRecurse(groupByCategories(data, rows.length ? rows : cols)); } else { dataRows.push([rowHeader, accumulator(data, accCatOrCB, accTypeOrInitVal)]); rawData = data; } - + return { table: columnHeaders.concat(dataRows), rawData: rawData }; } - + module.exports = { tableCreator: tableCreator, fixDataFormat: fixDataFormat, @@ -308,4 +336,4 @@ return /******/ (function(modules) { // webpackBootstrap /******/ ]) }); ; -//# sourceMappingURL=quick-pivot.js.map \ No newline at end of file +//# sourceMappingURL=quick-pivot.js.map diff --git a/test/logic.spec.js b/test/logic.spec.js index fad4f48..35246d3 100644 --- a/test/logic.spec.js +++ b/test/logic.spec.js @@ -262,6 +262,21 @@ describe('accumulator', function() { expect(accumulatedResults).to.equal(8); }); + it('average', function() { + var accumulatedResults = accumulator(data, 'age', 'average'); + + expect(accumulatedResults).to.equal(28.75); + }); + it('min', function() { + var accumulatedResults = accumulator(data, 'age', 'min'); + + expect(accumulatedResults).to.equal(28); + }); + it('max', function() { + var accumulatedResults = accumulator(data, 'age', 'max'); + + expect(accumulatedResults).to.equal(30); + }); }); it('should take an accumulation start value', function() {