Skip to content

Instantly share code, notes, and snippets.

@jimmed
Last active October 7, 2016 10:44
Show Gist options
  • Save jimmed/6608648 to your computer and use it in GitHub Desktop.
Save jimmed/6608648 to your computer and use it in GitHub Desktop.
An extension for underscore.js to generate tree structures based on Collections.

_.tree

_.tree is an extension for underscore.js, which converts flat Collections into tree structures.

Example

Take the following collection. Each item in the collection has an id and a parent_id, describing how it relates to other items.

var input = [
      { id: 1, name: 'Grandfather', parent_id: 0 },
      { id: 2, name: 'Father', parent_id: 1 },
      { id: 3, name: 'Son', parent_id: 2 },
      { id: 4, name: 'Daughter', parent_id: 2 }
    ];

By running _.tree(input), we would get something like the following:

{
  "id": 1,
  "name": "Grandfather",
  "parent_id": 0,
  "groups": [
    {
      "id": 2,
      "name": "Father",
      "parent_id": 1,
      "groups": [
        {
          "id": 3,
          "name": "Son",
          "parent_id": 2,
          "groups": []
        },
        {
          "id": 4,
          "name": "Daughter",
          "parent_id": 2,
          "groups": []
        }
      ]
    }
  ]
}

_.tree(data, rootId, pkName, fkName)

  • data is the input data. This is the only required parameter.
  • rootId is the value of the root item's primary key. Defaults to the first ID found, or 0.
  • pkName is the name of the primary key attribute. Defaults to id.
  • fkName is the name of the foreign key attribute. Defaults to parent_id.
(function() {
var attrEq = function(key, value, input) {
return input[key] && input[key] == value;
},
arrayToTree = function(data, rootId, pkName, fkName) {
pkName = pkName || 'id';
fkName = fkName || 'parent_id';
rootId = rootId || (_.first(data) || {})[pkName] || 0;
var output = _.clone(_.find(data, _.partial(attrEq, pkName, rootId))),
children = _.filter(data, _.partial(attrEq, fkName, rootId));
output.groups = _.map(children, function(child) {
return arrayToTree(data, child[pkName], pkName, fkName);
});
return output;
};
_.mixin({
tree: arrayToTree
});
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment