代码之家  ›  专栏  ›  技术社区  ›  Mohab

循环结构导致的Javascript递归

  •  0
  • Mohab  · 技术社区  · 9 年前

    cells :

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

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

    1. 名称

    2. 子数组,也包括具有名称和子数组的对象。数组中没有循环嵌套;一个孩子不能有任何父母作为孩子。

    下面是我写的函数:

    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(/\ +/)
    }
    

    getChildren(6) ,给出以下输出:

    给6岁的孩子
    []

    这是正确的,因为节点6没有子节点。

    但是在具有子节点的节点上调用函数,例如 getChildren(3) 即,给出:

    为3个孩子准备
    给5岁的孩子

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

    JSON.stringify on.调用函数on getChildren(3) 给出错误

    未捕获类型错误:将循环结构转换为JSON。

    我认为这是因为Jenny的对象无限嵌套在每个孩子下面。

    3 回复  |  直到 6 年前
        1
  •  1
  •   trincot    9 年前

    您使用全局变量,因此,当您递归调用函数时 儿童 小孩

    children.push(child)
    

    但是 儿童 将采用超出您预期的其他值,因此可以 小孩 也有不同的值,这两个值都与递归调用中的值不同(或者甚至更深入递归)。

    出于同样的原因,递归修改 将导致问题。

    使用 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; }
        2
  •  1
  •   Matti Price    9 年前

    将函数更改为以下内容:

    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”。这确保了它们被重新初始化,而不是通过函数调用持久化。这就是引起你问题的原因。

        3
  •  0
  •   VVildVVolf    9 年前

    如果我理解正确,您可以使用另一种方法来解析数据:

    //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);
      }
    }
    

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