2

So i have a tree stucture like below where i have a count attribute in the leaf nodes. i want to sum up the count and put the sum of counts against its parent. than so parent1 and parent2 have sum of their children. and than continue on from there, so grantparent has the sum of parent1 and parent2. i also have function to traverse the tree. But getting count i am unable to get.

Any ideas?

javascript

 function transverse(element, result, isSegmentData) {
        if (element instanceof Array){
            element.forEach(function (item) {
                { transverse(item, result, isSegmentData); }
            });
        }
        else if (element instanceof Object) {
            if (element.hasOwnProperty("count")) {

               // sum the count and provide to parent
            }
            if (element.hasOwnProperty("childNodes")) {
                transverse(element.childNodes, result, isSegmentData);
            }
        }
    }

tree structure

    [
  {
    "nodeId": 66318,
    "nodeName": "grand parent",
    "childNodes": [
      {
        "nodeId": 66323,
        "nodeName": "parent1",
        "childNodes": [
          {
            "nodeId": 66324,
            "nodeName": "child1",
            "childNodes": [],
            "count": 25
          },
          {
            "nodeId": 66334,
            "nodeName": "child2",
            "childNodes": [],
            "count": 85
          },
          {
            "nodeId": 66439,
            "nodeName": "child3",
            "childNodes": [],
            "count": 65
          },
          {
            "nodeId": 66462,
            "nodeName": "child4",
            "childNodes": [],
            "count": 954
          }
        ]
      },
      {
        "nodeId": 66323,
        "nodeName": "parent2",
        "childNodes": [
          {
            "nodeId": 66324,
            "nodeName": "child1",
            "childNodes": [],
            "count": 225
          },
          {
            "nodeId": 66334,
            "nodeName": "child2",
            "childNodes": [],
            "count": 815
          }
        ]
      }
    ]
  }
]
josh_boaz
  • 1,963
  • 7
  • 32
  • 69

3 Answers3

2

You could use a named function and call it for arrays again. Then assign count, if not given get the count from the children.

var data = [{ "nodeId": 66318, "nodeName": "grand parent", "childNodes": [{ "nodeId": 66323, "nodeName": "parent1", "childNodes": [{ "nodeId": 66324, "nodeName": "child1", "childNodes": [], "count": 25 }, { "nodeId": 66334, "nodeName": "child2", "childNodes": [], "count": 85 }, { "nodeId": 66439, "nodeName": "child3", "childNodes": [], "count": 65 }, { "nodeId": 66462, "nodeName": "child4", "childNodes": [], "count": 954 }] }, { "nodeId": 66323, "nodeName": "parent2", "childNodes": [{ "nodeId": 66324, "nodeName": "child1", "childNodes": [], "count": 225 }, { "nodeId": 66334, "nodeName": "child2", "childNodes": [], "count": 815 }] }] }];

data.reduce(function x(r, a) {
    a.count = a.count || Array.isArray(a.childNodes) && a.childNodes.reduce(x, 0) || 0;
    return r + a.count;
}, 0);

document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

If I understood your question correctly, you would like to iterate through the tree and reconcile the count of all nodes such that every node's count equals the count of all its descendants (if it has any). If that is the case, try this function (note, I did not test it but it should do what you want):

function reconcileCount(node) {
    var summedCountOfChildren = node.childNodes.reduce(function(_summedCount, childNode) {
        var childCount = childNode.childNodes && childNode.childNodes.length > 0 ? reconcileCount(childNode) : childNode.count;
        return _summedCount + (childCount || 0);
    }, 0);

    node.count = summedCountOfChildren;

    return node.count;
}

Basically, it takes a node and will reconcile the node passed as well as all nodes which are descendants of the node passed (i.e. you can pass your tree in, assuming the tree has one parent node, and it will reconcile your entire tree).

pQuestions123
  • 4,471
  • 6
  • 28
  • 59
1

Recursive function

You have to recursive loop on the elements and sum childrens by called the same function, Here it is:

function sumNodes(nodeList) {
    var sumChildren = function(node) {
        var sum = 0;
        for (var i = 0; i < node.childNodes.length && node.childNodes != null; i++) {
            sum += sumChildren(node.childNodes[i]);
        }
        node.sum = sum;
        return node.count == undefined ? sum : node.count;
    }
    for(var i=0; i<nodeList.length; i++){
        sumChildren(nodeList[i]);
    }

    return nodeList;
}

Call the sumNodes function with your tree as a parameter.

var treeWithSum = sumNodes(tree);
console.log(treeWithSum); // to see the results in the log

Full examples:

var data = [{
    "nodeId": 66318,
    "nodeName": "grand parent",
    "childNodes": [{
        "nodeId": 66323,
        "nodeName": "parent1",
        "childNodes": [{
            "nodeId": 66324,
            "nodeName": "child1",
            "childNodes": [{
                "nodeId": 66324,
                "nodeName": "child1",
                "childNodes": [],
                "count": 25
            }, {
                "nodeId": 66324,
                "nodeName": "child1",
                "childNodes": [{
                    "nodeId": 66324,
                    "nodeName": "child1",
                    "childNodes": [],
                    "count": 25
                }, {
                    "nodeId": 66324,
                    "nodeName": "child1",
                    "childNodes": [{
                        "nodeId": 66324,
                        "nodeName": "child1",
                        "childNodes": [],
                        "count": 25
                    }, {
                        "nodeId": 66324,
                        "nodeName": "child1",
                        "childNodes": [],
                        "count": 25
                    }]
                }]
            }]
        }, {
            "nodeId": 66334,
            "nodeName": "child2",
            "childNodes": [],
            "count": 85
        }, {
            "nodeId": 66439,
            "nodeName": "child3",
            "childNodes": [],
            "count": 65
        }, {
            "nodeId": 66462,
            "nodeName": "child4",
            "childNodes": [],
            "count": 954
        }]
    }, {
        "nodeId": 66323,
        "nodeName": "parent2",
        "childNodes": [{
            "nodeId": 66324,
            "nodeName": "child1",
            "childNodes": [],
            "count": 225
        }, {
            "nodeId": 66334,
            "nodeName": "child2",
            "childNodes": [],
            "count": 815
        }]
    }]
}]


function sumNodes(nodeList) {
    var sumChildren = function(node) {
        var sum = 0;
        for (var i = 0; i < node.childNodes.length && node.childNodes != null; i++) {
            sum += sumChildren(node.childNodes[i]);
        }
        node.sum = sum;
        return node.count == undefined ? sum : node.count;
    }
    for(var i=0; i<nodeList.length; i++){
  sumChildren(nodeList[i]);
 }

 return nodeList;
}

$("#results").html(JSON.stringify(sumNodes(data), null, 4));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<pre id="results"></pre>
David Antoon
  • 815
  • 6
  • 18