获取给定JSON树级别的节点数

时间:2016-07-08 22:23:48

标签: javascript json recursion

我有一个带有子节点的JSON树结构,我想知道在给定的结构级别存在多少个节点。我目前有这种递归结构:

assets.json

这不起作用 - 任何帮助都将不胜感激!

2 个答案:

答案 0 :(得分:0)

您在此处展示的方法存在一些缺陷。

第一次停止 遇到目标深度的深度将导致只计算那里的第一组子项,这只是一个子集。

使用诸如forEach之类的迭代函数将在其迭代中进行调用,但它本身不会返回值,并且在回调内部使用return的所示方法也没有效果。

  

forEach()为每个数组元素执行一次回调函数;与map()或reduce()不同,它总是返回undefined值并且不可链接。典型的用例是在链的末尾执行副作用。 - MDN: Array.prototype.forEach()

更好的方法是按深度分析整个树结构的宽度,并在完成后返回索引值。可以通过在给定深度之后不递归来使其短路,但是我在对象depths中进行了完整分析以获得完整的示例。

如下所示,这使用IIFE递归树,构建一个对象,其关键是深度,其值是宽度,然后根据原始函数调用的输入深度返回关联的宽度。

var testObj = {
 children : [ 
  { children : [ { children : [ ] } ] },
  { children : [ ] },
  { children : [ { children : [ ] } ] }
 ]
};

var getNumNodesAtLevel = 
    function (root, depth) {
      var depths = {0:1};

      (function recurTree(node,level){
        level++;
        
        if(depths[level] == void 0){
          depths[level] = node.children.length;
        }else{
          depths[level] += node.children.length;
        }

        //optionally short circuit to avoid excessive recursion
        //if(level+1 > depth) return;
        for(var i = 0; i < node.children.length; i++){
            recurTree(node.children[i],level);  
        }
      })(root,0)
      
      return depths[depth];
    };

console.log(getNumNodesAtLevel(testObj,1));
console.log(getNumNodesAtLevel(testObj,2));

答案 1 :(得分:0)

你很亲密。你只需将孩子的长度存放在某处。

一旦达到少于所需的一个级别,该函数将返回子项的长度。

树中较高的所有节点只会将从子节点收集的值添加到零并将其传回,直到到达根节点。

var getNumNodesAtLevel = function(node, curr, desired) {
  if (curr === (desired - 1))
    return node.children.length;

  var count = 0;
  node.children.forEach(function(child) {
    count += getNumNodesAtLevel(child, curr + 1, desired);
  });
  return count;
};

这种方法的问题是当期望的级别大于树的深度或者它是零时(根级别应该返回1),将返回0。

为了解决这个问题,您可以进行关闭并检查有问题的值。

也无需每次手动发送起始等级。

&#13;
&#13;
var test = {
 children : [ 
  { children : [ { children : [ ] } ] },
  { children : [ ] },
  { children : [ { children : [ ] } ] }
 ]
};

var getNumNodesAtLevel = (function() {

  var getNumNodesAtLevel = function(node, curr, desired) {
    if (curr === (desired - 1))
      return node.children.length;

    var count = 0;
    node.children.forEach(function(child) {
      count += getNumNodesAtLevel(child, curr + 1, desired);
    });
    return count;
  };

  return function(root, desired) {

    if (desired === 0)
      return 1;

    var count = getNumNodesAtLevel(root, 0, desired);
    if (count === 0)
      return null; // you could throw an error here

    return count;

  };

}());

console.log(getNumNodesAtLevel(test, 0)); // 1
console.log(getNumNodesAtLevel(test, 1)); // 3
console.log(getNumNodesAtLevel(test, 2)); // 2
console.log(getNumNodesAtLevel(test, 3)); // null
console.log(getNumNodesAtLevel(test, 4)); // null
&#13;
&#13;
&#13;