Created
March 28, 2014 16:59
Revisions
-
J. Voigt revised this gist
Mar 28, 2014 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -57,6 +57,7 @@ var byColor = function(d) { var byQuantity = function(d) { return d.quantity; }; ``` @@ -116,12 +117,12 @@ expected = { Nest by key names: ```js deepEqual(nest(data, ['type', 'color']), expected); ``` Nest by key functions: ```js deepEqual(nest(data, [byType, byColor]), expected); ``` -
J. Voigt created this gist
Mar 28, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,127 @@ # nest.js A multi-level [groupBy](http://underscorejs.org/#groupBy) for arrays inspired by D3's [nest](https://github.com/mbostock/d3/wiki/Arrays#-nest) operator. Nesting allows elements in an array to be grouped into a hierarchical tree structure; think of it like the `GROUP BY` operator in SQL, except you can have multiple levels of grouping, and the resulting output is a tree rather than a flat table. The levels in the tree are specified by key functions. See [this fiddle](http://jsfiddle.net/V7an5/3/) for live demo. ## Implementation Depends on lodash's [groupBy](http://lodash.com/docs#groupBy) and [mapValues](http://lodash.com/docs#mapValues): ```js _ = require('lodash'); var nest = function (seq, keys) { if (!keys.length) return seq; var first = keys[0]; var rest = keys.slice(1); return _.mapValues(_.groupBy(seq, first), function (value) { return nest(value, rest) }); }; module.exports = nest; ``` ## Usage Input data to be nested: ```js var data = [ { type: "apple", color: "green", quantity: 1000 }, { type: "apple", color: "red", quantity: 2000 }, { type: "grape", color: "green", quantity: 1000 }, { type: "grape", color: "red", quantity: 4000 } ]; ``` Key functions used for grouping criteria: ```js var byType = function(d) { return d.type; }; var byColor = function(d) { return d.color; }; var byQuantity = function(d) { return d.quantity; ``` ## First Example Expected output when grouping by `color` and `quantity`: ```js var expected = { green: { "1000": [ { type: 'apple', color: 'green', quantity: 1000 }, { type: 'grape', color: 'green', quantity: 1000 } ] }, red: { "2000": [ { type: 'apple', color: 'red', quantity: 2000 } ], "4000": [ { type: 'grape', color: 'red', quantity: 4000 } ] } }; ``` Nest by key name: ```js deepEqual(nest(data, ['color', 'quantity']), expected); ``` Nest by key functions: ```js deepEqual(nest(data, [byColor, byQuantity]), expected); ``` ## Second Example Expected output when grouping by `type` and `color`: ```js expected = { apple: { green: [ { "type": "apple", "color": "green", "quantity": 1000 } ], red: [ { "type": "apple", "color": "red", "quantity": 2000 } ] }, grape: { green: [ { "type": "grape", "color": "green", "quantity": 1000 } ], red: [ { "type": "grape", "color": "red", "quantity": 4000 } ] } }; ``` Nest by key names: ```js eq(nest(data, ['type', 'color']), expected); ``` Nest by key functions: ```js eq(nest(data, [byType, byColor]), expected); ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,77 @@ var nest = require('nest'); var assert = require('assert'); var eq = assert.deepEqual; // input data to be nested var data = [ { type: "apple", color: "green", quantity: 1000 }, { type: "apple", color: "red", quantity: 2000 }, { type: "grape", color: "green", quantity: 1000 }, { type: "grape", color: "red", quantity: 4000 } ]; /* FIRST EXAMPLE */ // expected output, grouping by `color` and `quantity` var expected = { green: { "1000": [ { type: 'apple', color: 'green', quantity: 1000 }, { type: 'grape', color: 'green', quantity: 1000 } ] }, red: { "2000": [ { type: 'apple', color: 'red', quantity: 2000 } ], "4000": [ { type: 'grape', color: 'red', quantity: 4000 } ] } }; // key functions used for grouping criteria var byType = function(d) { return d.type; }; var byColor = function(d) { return d.color; }; var byQuantity = function(d) { return d.quantity; }; // nest by key name eq(nest(data, ['color', 'quantity']), expected); // nest by key function eq(nest(data, [byColor, byQuantity]), expected); /* SECOND EXAMPLE */ // expected output, grouping by `type` and `color` expected = { apple: { green: [ { "type": "apple", "color": "green", "quantity": 1000 } ], red: [ { "type": "apple", "color": "red", "quantity": 2000 } ] }, grape: { green: [ { "type": "grape", "color": "green", "quantity": 1000 } ], red: [ { "type": "grape", "color": "red", "quantity": 4000 } ] } }; // nest by key names eq(nest(data, ['type', 'color']), expected); // nest by key function eq(nest(data, [byType, byColor]), expected); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,13 @@ _ = require('lodash'); var nest = function (seq, keys) { if (!keys.length) return seq; var first = keys[0]; var rest = keys.slice(1); return _.mapValues(_.groupBy(seq, first), function (value) { return nest(value, rest) }); }; module.exports = nest;