diff --git a/Readme.md b/Readme.md index 8863bb9..f909434 100644 --- a/Readme.md +++ b/Readme.md @@ -51,6 +51,28 @@ groupBy(users, function(user){ }) ``` +### groupBy(array, [prop1, prop2]) +### groupBy(array, prop1, prop2) +### groupBy(array, [fn1, fn2]) +### groupBy(array, fn1, fn2) + + Also groups by multiple keys + +```js +groupBy(nodes, 'type', 'version'); +``` + +yields: + +```js +{ log: + { '1.0.0': [ { type: 'log', version: '1.0.0' } ], + '1.1.0': [ { type: 'log', version: '1.1.0' } ], + '1.3.0': [ { type: 'log', version: '1.3.0' } ] }, + app: { '1.0.0': [ { type: 'app', version: '1.0.0' } ], + '1.1.0': [ { type: 'app', version: '1.1.0' } ] } } +``` + ## License MIT diff --git a/index.js b/index.js index 70b0220..3b7bd1d 100644 --- a/index.js +++ b/index.js @@ -9,21 +9,29 @@ var toFunction = require('to-function'); * Group `arr` with callback `fn(val, i)`. * * @param {Array} arr - * @param {Function|String} fn or prop + * @param {Array|Function|String} fn or prop, or array of fn or prop * @return {Array} * @api public */ -module.exports = function(arr, fn){ +module.exports = function(arr, fns){ var ret = {}; var prop; - fn = toFunction(fn); + var obj; + var fn; + fns = {}.toString.call(fns) === '[object Array]' ? fns : [].slice.call(arguments, 1); + fns = fns.map(toFunction); for (var i = 0; i < arr.length; ++i) { - prop = fn(arr[i], i); - ret[prop] = ret[prop] || []; - ret[prop].push(arr[i]); + obj = ret; + for (var j = 0; j < fns.length; ++j) { + fn = fns[j]; + prop = fn(arr[i], i); + obj[prop] = obj[prop] || (j === fns.length - 1 ? [] : {}); + obj = obj[prop]; + } + obj.push(arr[i]); } return ret; -}; \ No newline at end of file +}; diff --git a/test/index.js b/test/index.js index 8d3f984..402ece1 100644 --- a/test/index.js +++ b/test/index.js @@ -18,6 +18,24 @@ describe('groupBy(arr, prop)', function(){ }) }) +describe('groupBy(arr, prop1, prop2)', function(){ + it('should group by multiple properties', function () { + var ret = groupBy(nodes, 'type', 'version'); + Object.keys(ret.log).should.have.length(3); + ret.log['1.0.0'].should.have.length(1); + ret.app['1.1.0'].should.have.length(1); + }) +}) + +describe('groupBy(arr, [prop1, prop2])', function(){ + it('should group by multiple properties', function () { + var ret = groupBy(nodes, ['type', 'version']); + Object.keys(ret.log).should.have.length(3); + ret.log['1.0.0'].should.have.length(1); + ret.app['1.1.0'].should.have.length(1); + }) +}) + describe('groupBy(arr, fn)', function(){ it('should group by the returned property', function(){ var ret = groupBy(nodes, function(node){ @@ -28,4 +46,31 @@ describe('groupBy(arr, fn)', function(){ ret['1.1.0'].should.have.length(2); ret['1.3.0'].should.have.length(1); }) -}) \ No newline at end of file +}) + +describe('groupBy(arr, fn1, fn2)', function(){ + it('should group by the returned properties', function () { + var ret = groupBy(nodes, function(node){ + return node.type; + }, function(node){ + return node.version; + }); + Object.keys(ret.log).should.have.length(3); + ret.log['1.0.0'].should.have.length(1); + ret.app['1.1.0'].should.have.length(1); + }) +}) + +describe('groupBy(arr, [fn1, fn2])', function(){ + it('should group by the returned properties', function () { + var ret = groupBy(nodes, function(node){ + return node.type; + }, function(node){ + return node.version; + }); + Object.keys(ret.log).should.have.length(3); + ret.log['1.0.0'].should.have.length(1); + ret.app['1.1.0'].should.have.length(1); + }) +}) +