Javascript 递归导致循环结构

Javascript recursion caused circular structure

我有以下二维数组cells:

ID  Name    Parent
1   Bob     0
2   Alice   1
3   John    2
4   Jane    2
5   Jenny   3
6   Jonny   2

我想将其转换为嵌套的 JSON 格式,这样每个 object 都具有以下属性:

  1. 姓名

  2. children 的数组,其中还包括 object 的名称和 children 的数组。数组中没有循环嵌套; a child 不能有任何 parents 作为 children.

下面是我写的函数:

function getChildren(node){
    console.log('Getting Children for' + node)
    children = []
    for(i = 0;i < cells.length; i++){
        if(cells[i][2] == node){
            cell = cells[i]
            child = {}
            child.name = cell[1]
            child.children = getChildren(cell[0])
            children.push(child)
        }
    }
    return children
}


text = "ID  Name    Parent\n1   Bob     0\n2   Alice   1\n3   John                  2\n4   Jane    2\n5   Jenny     3\n6   Jonny   2\n"

lines = text.split('\n')
cells = []
for(i = 0; i < lines.length; i++){
    cells[i] = lines[i].split(/\ +/)
}

在节点 6 getChildren(6) 上调用函数,得到以下输出:

Getting Children for6
[]

这是正确的,因为节点 6 没有 children.

但是在 children 节点上调用函数,例如 getChildren(3),给出:

Getting Children for3
Getting Children for5

Object
    children: Array[1]
        0: Object
            children: Array[1]
                0: Object
                    children: Array[1]
                    name: "Jenny"
                    length: 1
            name: "Jenny"
            length: 1
    name: "Jenny"

从控制台输出看来它调用了正确的函数,但为什么 "jenny" 的 object 无限嵌套在所有 children 下?

我想以 JSON object 结束,我可以在 JSON.stringify 上使用它。在 getChildren(3) 上调用函数给出错误

Uncaught TypeError: Converting circular structure to JSON.

我认为这是因为 Jenny 的 object 无限嵌套在每个 child 下。

将您的函数更改为以下内容

function getChildren(node){
    console.log('Getting Children for' + node)
    var children = []
    for(i = 0;i<cells.length; i++){
        if(cells[i][2] == node){
            var cell = cells[i]
            child = {}
            child.name = cell[1]
            child.children = getChildren(cell[0])
            children.push(child)
        }}
    return children
}

注意在变量声明之前添加的 "var"。这确保它们被重新初始化,而不是通过函数调用持久化。这就是导致您出现问题的原因。

你使用了全局变量,因此,当你递归调用你的函数时,像 childrenchild 这样的变量可以得到新的值。当你退出递归调用时,你会做:

children.push(child)

.. 但是 children 会取与您预期不同的值,因此 child 也可以有不同的值,两者都来自它们在递归调用中是什么(或者从递归的更深处)。

同理递归修改i也会出问题

使用 var 使您的变量成为函数的局部变量,它将起作用:

function getChildren(node){
    console.log('Getting Children for' + node)
    var children = []
    for(var i = 0;i<cells.length; i++){
        if(cells[i][2] == node){
            var cell = cells[i]
            var child = {}
            child.name = cell[1]
            child.children = getChildren(cell[0])
            children.push(child)
        }}
    return children
}

function getChildren(node){
    var children = []
    for(var i = 0;i<cells.length; i++){
        if(cells[i][2] == node){
            var cell = cells[i]
            var child = {}
            child.name = cell[1]
            child.children = getChildren(cell[0])
            children.push(child)
        }}
    return children
}

var text = "ID  Name    Parent\n1   Bob     0\n2   Alice   1\n3   John                  2\n4   Jane    2\n5   Jenny     3\n6   Jonny   2\n"

var lines = text.split('\n')
var cells = []
for(var i = 0; i< lines.length; i++){
  cells[i] = lines[i].split(/\ +/)
}

console.log(JSON.stringify(getChildren(0), null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

如果我没理解错的话,您可以使用另一种方式来解析您的数据:

//separete the values
var input = [
    [1,   'Bob',     0],
    [2,   'Alice',   1],
    [3,   'John',    2],
    [4,   'Jane',    2],
    [5,   'Jenny',   3],
    [6,   'Jonny',   2]
];

var entities = []; //I belive that the ids are uniq

for (var i = 0; i < input.length; i++){
    var id = input[i][0];
  entities[id] = {
    id: id, 
    name: input[i][1], 
    children : [], 
    parent: input[i][2]
  };
}

for (var i in entities){
    var current = entities[i];
  var parent = entities[current.parent];
  delete current.parent;

  if (parent){
        parent.children.push(current);
  }
}

通过这种方式,您可以通过索引从实体数组中找到特定元素,或者在解析开始时获取根元素(元素数组中不包含其父元素的元素)