将顺序编号添加到嵌套对象树中的Javascript对象

时间:2016-10-05 13:42:43

标签: javascript recursion

我有一个类似下面的对象,我正在寻找一种方法来为树中的每个子对象添加一个属性。也就是说,我想为从0到n计数的对象添加一个数字。我知道我可以使用递归函数遍历对象,但由于范围可变,我无法使用简单的递增变量来计算我在树中的数量。

当前对象:

var tree = [
{
    name: 'a',
    children: []
},{
    name: 'b',
    children: [
        {
            name: 'c',
            children: []
        }
    ]
},
{
    name: 'd',
    children: [
        {
            name: 'e',
            children: [
                {
                    name: 'f',
                    children: []
                },
                {
                    name: 'g',
                    children: []
                }
            ]
        }
    ]
}
];

所需对象:

var tree = [
{
    name: 'a',
    number: 0,
    children: []
},{
    name: 'b',
    number: 1,
    children: [
        {
            name: 'c',
            number: 2,
            children: []
        }
    ]
},
{
    name: 'd',
    number: 3,
    children: [
        {
            name: 'e',
            number: 4,
            children: [
                {
                    name: 'f',
                    number: 5,
                    children: []
                },
                {
                    name: 'g',
                    number: 6,
                    children: []
                }
            ]
        }
    ]
}
];

2 个答案:

答案 0 :(得分:2)

使用计数器作用域引发的问题可以通过在闭包中定义计数器来解决,在闭包中也可以使用递归函数。

这是一个ES6函数:

function numberNodes(tree, n = 0) {
    return (function recurse(children) {
        return children.map( node => Object.assign({}, node, {
            number: n++,
            children: recurse(node.children)
        }) );
    })(tree);
}
// Sample data
var tree = [{ name: 'a', children: []},
            { name: 'b', children: 
                [{ name: 'c', children: []}]},
            { name: 'd', children: 
                [{ name: 'e', children: 
                    [{ name: 'f', children: []}, { name: 'g', children: []}]}]}];

// Return tree with numbers added:
tree = numberNodes(tree);

// Output result
console.log(tree);

请注意,此函数不会改变您传递的树,只有返回值具有添加的属性。所以这是函数式编程的做法。

答案 1 :(得分:1)

您只需要在递归函数之外设置计数器变量,并在循环对象之前递增它。



var tree = [{"name":"a","children":[]},{"name":"b","children":[{"name":"c","children":[]}]},{"name":"d","children":[{"name":"e","children":[{"name":"f","children":[]},{"name":"g","children":[]}]}]}];

function addNumber(input) {
  var counter = 0;

  function rec(data) {
    data.forEach(function(e) {
      if (typeof e == 'object' && !Array.isArray(e)) {
        e.number = counter++;
        for (var p in e) {
          if (typeof e[p] == 'object') rec(e[p])
        }
      } 
    })
  }
  rec(input)
}

addNumber(tree);
console.log(tree)