在嵌套对象树中为Javascript对象添加序号

Add Sequential Number To Javascript Objects In Nested Object Tree

本文关键字:对象 添加 Javascript 嵌套      更新时间:2023-09-26

我有一个像下面这样的对象,我正在寻找一种方法来添加一个属性到树中的每个子对象。也就是说,我想给对象添加一个从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: []
                }
            ]
        }
    ]
}
];

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

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)

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

下面是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);

注意,这个函数不会改变传递给它的树,只有返回值具有添加的属性。这是一种函数式编程方法