node package manager
Loosely couple your services. Use Orgs to version and reuse your code. Create a free org »

underscore.nest

Underscore.Nest

Underscore.Nest is an extenstion for converting flat data into nested tree structures. It works in Node.js and is AMD compatible.

For example, if your data looks like this:

var data = [
    { c1 : "A", c2 : "B", c3 : "C", v : 10 },
    { c1 : "A", c2 : "C", c3 : "D", v : 10 },
    { c1 : "B", c2 : "B", c3 : "C", v : 10 }
  ];

And you want it to look like this:

{
  children : [
    { name : 'A', index : 0, children : [
      { c1 : "A", c2 : "B", c3 : "C", v : 10 },
      { c1 : "A", c2 : "C", c3 : "D", v : 10 }
    ]},
    { name : 'B', index : 1, children : [
      { c1 : "B", c2 : "B", c3 : "C", v : 10 }
    ]}
  ]
}

You can accomplish that by using underscore.nest like so:

  _.nest(data, "c1");

Node.js

npm install underscore.nest

Get your favorite underscore flavor:

// get your requirements in order. 
var u = require('underscore');
u.nst = require('underscore.nest');
 
// run your nesting 
u.nst.nest(data, 'c1');

API:

Basic API:

_.nest(data, columnsToReduceBy, reduceFunction);
  • data - An array of objects
  • columnsToReduceBy - Underscore.nest can infinitly nest your data. You can either nest by a single field by passing the name of that field, or an array of fields.
  • reduceFunction - Optional. If you want to reduce your resulting children into a single value result, pass a function that takes an array of objects and returns a single value.

Note that every child grouping will recieve an index property that will mark its order in the heirarchy.

Examples:

Nest With Reduce:

If you pass in a reduce function, instead of having a children property set, you will have a value property set that will be the result of the reduce function call.

 
var data = [
  { c1 : "A", c2 : "B", c3 : "C", v : 10 },
  { c1 : "A", c2 : "C", c3 : "D", v : 10 },
  { c1 : "B", c2 : "B", c3 : "C", v : 10 }
];
 
_.nest(data, "c1", _.sum); // _.sum is from underscore.math 

Results in:

{
  children : [
    { name : 'A', index : 0, value : 20 },
    { name : 'B', index : 1, value : 10 }
  ]
};

Multi Level Nesting

If you pass an array of properties instead of a single string for the second argument, nest will create a nesting based on each of those arguments like so:

var data = [
  { c1 : "A", c2 : "B", c3 : "C", v : 10 },
  { c1 : "A", c2 : "C", c3 : "D", v : 10 },
  { c1 : "B", c2 : "B", c3 : "C", v : 10 }
];
 
_.nest(data, ["c1", "c2"]);

Results in:

{ children :
  [
    { name : "A",
      children : [
        { name : "B",
          children :[
            { c1 : "A", c2 : "B", c3 : "C", v :10 }
          ],
          index : 0},
        { name : "C", 
          children :[
            { c1 : "A", c2 : "C", c3 : "D", v :10 }
          ],
          index : 1
        }
      ],
      index : 0 },{
      name : "B",
      index : 1,
      children : [
        { name : "B",
          index : 0
          children : [
            { c1 : "B", c2 : "B", c3 : "C", v : 10 }
          ]
      }]
    }
  ]
};

Questions?

Contact @ireneros on twitter, iros on IRC email me.