1

I have an array of objects like:

[{id: 1, parentId: 0, title: 'root'},
{id: 2, parentId: 1, title: 'home'},
{id: 3, parentId: 1, title: 'level 1'},
{id: 4, parentId: 2, title: 'level 2'}]

I would like to create functions on this array so I can use calls like:

var node = library.findById(4);

and also to extend the actual objects themselves so I can create functions like:

var parent = node.parent();
var grandparent = parent.parent();
var children = grandparent.children();

So far I am doing it like this:

// server.js
var library = require('./library').init(nodes);

// library.js
'use strict';
var _ = require('lodash'),
    Node = require('./node');

function objectifyNodes(lib, nodes) {
  var a = [];
  nodes.forEach(function (n) {
    a.push(new Node(lib, n));
  });
  return a;
}

function Library(nodes) {
  this.nodes = objectifyNodes(this, nodes);
}

Library.prototype.findById = function(id) {
  var x = _.find(this.nodes, function(node) {return node.id === id; });
  if (x) { return x; }
  return null;
};

module.exports = {
    init: function(nodes) {
      var lib = new Library(nodes);
      return lib;
    }
};

// node.js
'use strict';
var _ = require('lodash');

function Node(lib, properties) {
  _.extend(this, properties);
  this.lib = lib;
}

Node.prototype.parent = function() {
  return this.lib.findById(this.parentId);
};

Node.prototype.children = function() {
  return this.lib.findByParentId(this.id);
};

module.exports = Node;

Given that they could potentially be 1000's of nodes is this a reasonable way to implement this? Is there a better pattern I could use for a solution?

4
  • I don't think thousands of nodes should be a problem, but it depends on how much RAM your server has, what else you are requiring it to store in memory, and several other variables. If it gets slow, you may want to switch to a database driven model. Commented Apr 20, 2015 at 23:45
  • In terms of performance, one thing I can suggest is saving your nodes in an objects with the ids as keys. Then you access a certain node simply by library.nodes[id]. Of course, this only makes sense if you don't care about the ordering of the nodes. Commented Apr 20, 2015 at 23:59
  • @basilikum—or create an index object of id:object, provided the IDs are unique. It could even be {id: {node: obj, parent:obj, grandParent: obj, ...}, id{...}} ;-) Commented Apr 21, 2015 at 0:27
  • @mkoryak I'm creating a new object type and defining properties on it - I'm not sure this is an antipattern? The reason for doing this is I want to expose these objects so they can be called in a certain way by other developers i.e. an API Commented Apr 22, 2015 at 21:32

1 Answer 1

1

You should store the nodes by their ids (which I assume are unique), so that you can quickly access them. Use an array (for not-too-sparse integer ids), object (by default) or Map (in recent node.js releases).

function objectifyNodes(lib, nodes) {
  var a = {};
  nodes.forEach(function (n) {
    a[n.id] = new Node(lib, n);
  });
  return a;
}


Library.prototype.findById = function(id) {
  return this.nodes[id] || null;
};

That way, it won't have to sift through the full array every time. The rest of your library seems fine.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I'll probably keep it as is as we'll likely be adding in more functions to the library such as Children() which will filter on parentId. My main concern was whether calling objectifyNodes up front was the best way and it sounds like this is OK
Well, you can still filter objects…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.