遍历一棵树,获得每个物体的深度

时间:2016-12-27 10:51:35

标签: javascript recursion tree

我有一个JavaScript对象,让我们称它为“obj”。我想遍历这个对象及其后代,并找出每个对象有多少个后代,并在对象的属性上保存这个数字,如obj.numOfDescendants或其他东西。如何以递归方式完成?

我尝试了以下操作,但它没有工作:

var traversTree = function(obj) {
    for (let k in obj) {
        if (typeof obj[k] === "object") {
            if (!obj["numOfDescendants"])
                obj["numOfDescendants"] = 0;
            obj.numOfDescendants += traversTree(obj[k]); // Here is where I'm stuck.
                                                         // What do I return here
                                                         // in order to sum the
                                                         // depth?
            return 1;
        }
    }
}

有人指出我错了吗?

1 个答案:

答案 0 :(得分:2)

一些问题:

  • 您希望traversTree返回一个值:

    obj.numOfDescendants += traversTree(obj[k]);
    

    ...但在所有情况下,您都没有从中返回值,仅在某些情况下。您希望函数始终返回值。

  • 在循环结束之前,你过早地回来了。您需要在对象的对象孩子的所有上添加调用traversTree的结果。

  • (与上一点相关。)您在循环中重新更新obj.numOfDescendants,但在循环结束之前,您实际上并不知道该数字。

    < / LI>
  • 我们需要计算我们刚刚输入的那个,所以在添加后代时,我们需要在其上调用traversTree 1的结果。

这就是:

var traversTree = function(obj) {
    var descendants = 0;
    for (let k in obj) {
        if (typeof obj[k] === "object") {
            descendants += traversTree(obj[k]) + 1;
        }
    }
    obj.numOfDescendants = descendants;
    return descendants;
};

示例:

&#13;
&#13;
var traversTree = function(obj) {
  var descendants = 0;
  for (let k in obj) {
    if (typeof obj[k] === "object") {
      descendants += traversTree(obj[k]) + 1;
    }
  }
  obj.numOfDescendants = descendants;
  return descendants;
};

console.log("Example 1:");
var o1 = {
  test: {}
};
traversTree(o1);
console.log(o1);

console.log("Example 2:");
var o2 = {
  a: {},
  b: {
    c: {}
  }
};
traversTree(o2);
console.log(o2);

console.log("Example 3:");
var o3 = {
  a: {},
  b: {
    c: [{}, {x:{z:"y"}}, {}]
  }
};
traversTree(o3);
console.log(o3);
&#13;
.as-console-wrapper {
  max-height: 100% !important;
}
&#13;
&#13;
&#13;

附注:您已在代码中同时使用varletlet是ES2015的新关键字。如果您正在使用ES2015或更高版本并切换到使用let,那么最好始终如一地执行此操作,而不是有时使用var。另请参阅尽可能使用const和箭头函数,例如:

const traversTree = obj => {
    let descendants = 0;
    for (const k in obj) {
        if (typeof obj[k] === "object") {
            descendants += traversTree(obj[k]) + 1;
        }
    }
    obj.numOfDescendants = descendants;
    return descendants;
};

上面的constk可能看起来很奇怪,但是在初始值设定项中声明迭代器变量时for循环的机制实际上是这样的每个循环迭代都有一个新的kk的值在循环体中永远不会改变,所以const实际上在那里工作。但是,当然,它看起来有点奇怪。