Skip to content

Commit

Permalink
feat(Tree): implement sumOnProperty()
Browse files Browse the repository at this point in the history
This commit implements the sumOnProperty() function to sum tree nodes
on a given property.  Parent nodes are given the values of the sums of
their children.
  • Loading branch information
jniles committed Jan 26, 2018
1 parent 85892b6 commit 663165a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
34 changes: 30 additions & 4 deletions server/lib/Tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,46 @@ function flatten(tree, depth, pruneChildren = true) {
}, []);
}

/**
* @function sumOnProperty
*
* @description
* Computes the value of all parent nodes in the tree as the sum of the values
* of their children for a given property.
*/
function sumOnProperty(node, prop) {
if (node.children.length > 0) {
// recursively compute the value of node[prop] by summing all child[prop]s
node[prop] = node.children.reduce((value, child) =>
value + sumOnProperty(child, prop), 0);
}

return node[prop];
}

class Tree {
constructor(data = [], parentKey = 'parent', rootId = 0) {
constructor(data = [], options = {
parentKey : 'parent',
rootId : 0,
}) {
this._data = data;
this._parentKey = parentKey;
this._rootId = rootId;

this._parentKey = options.parentKey;
this._rootId = options.rootId;

// build the tree with the provided root id and parentKey
this._tree = buildTreeFromArray(_.cloneDeep(data), rootId, parentKey);
this._tree = buildTreeFromArray(_.cloneDeep(data), this._rootId, this._parentKey);
}

toArray() {
return flatten(this._tree);
}

sumOnProperty(prop) {
this._tree.forEach(node => {
sumOnProperty(node, prop);
});
}
}

module.exports = Tree;
40 changes: 36 additions & 4 deletions test/server-unit/Tree.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ function TreeUnitTests() {
* ROOT
* / | \
* id:1 id:4 id:6
* / \
* id:2 id:3
* / / \
* id:2 id:7 id:3
* /
* id:5
*/
Expand All @@ -21,15 +21,26 @@ function TreeUnitTests() {
}, {
id : 3,
parent : 6,
valueA : 10,
valueB : 2,
}, {
id : 4,
parent : 0,
valueA : 30,
valueB : 4,
}, {
id : 5,
parent : 2,
valueA : 9,
valueB : 7,
}, {
id : 6,
parent : 0,
}, {
id : 7,
parent : 6,
valueA : 10,
valueB : 19,
}];

it('#constructor() should populate private variables', () => {
Expand Down Expand Up @@ -64,11 +75,11 @@ function TreeUnitTests() {
expect(node4.children).to.have.length(0);
});

it('#constructor() node id:6 should have one child', () => {
it('#constructor() node id:6 should have two children', () => {
const tree = new Tree(nodes)._tree;
const node6 = tree[2];
expect(node6.id).to.equal(6);
expect(node6.children).to.have.length(1);
expect(node6.children).to.have.length(2);
});

it('#toArray() should return an array', () => {
Expand All @@ -82,6 +93,27 @@ function TreeUnitTests() {
expect(node).to.have.property('depth');
});
});

it('#sumOnProperty() should compute the balances of level 1 nodes', () => {
const tree = new Tree(nodes);
const subTree = tree._tree;

// first level should not be defined
expect(subTree[0].valueA).to.be.undefined;
expect(subTree[0].valueB).to.be.undefined;

// this is a level 1 leaf node, so its values are known.
expect(subTree[1].valueA).to.equal(30);
expect(subTree[1].valueB).to.equal(4);

tree.sumOnProperty('valueA');
expect(subTree[0].valueA).to.equal(9);
expect(subTree[0].valueB).to.be.undefined;

// this condition sums multiple leaves
tree.sumOnProperty('valueB');
expect(subTree[2].valueB).to.equal(21); // 2 + 19
});
}

describe('Tree.js', TreeUnitTests);

0 comments on commit 663165a

Please sign in to comment.