如何替换为递归函数?

时间:2019-05-08 05:05:01

标签: javascript

const result = [];
let remainIndex = [];
const res = [
  {
    traceInfo: {
      node4: {
        traceId: "F"
      },
      node5: {
        traceId: "G"
      }
    },
    name: "FG"
  },
  {
    traceInfo: {
      node4: {
        traceId: "B"
      },
      node5: {
        traceId: "D"
      }
    },
    name: "BD"
  },
  {
    traceInfo: {
      node4: {
        traceId: "B"
      },
      node5: {
        traceId: "C"
      }
    },
    name: "BC"
  },
  {
    nodeId: "C-E",
    traceInfo: {
      node4: {
        traceId: "C"
      },
      node5: {
        traceId: "E"
      } 
    },
    name: "CE"
  },
  {
    traceInfo: {
      node4: {
        traceId: "A"
      },
      node5: {
        traceId: "B"
      }
    },
    name: "AB"
  },
  {
    traceInfo: {
      node4: {
        traceId: "E"
      },
      node5: {
        traceId: "F"
      }
    },
    name: "EF"
  },
  {
    traceInfo: {
      node4: {
        traceId: "A"
      },
      node5: {
        traceId: "A"
      }
    },
    name: "AA"
  }
];

function findRoot(res) {
  res.forEach((row, index) => {
    if (row.traceInfo.node4.traceId === row.traceInfo.node5.traceId) {
      // root
      result.push({
        name: row.traceInfo.node4.traceId,
        children: []
      });
    } else {
      remainIndex.push(index);
    }
  });
}

function processItems(res) {
  let remainIndexNext = [];
  for (var i = 0; i < remainIndex.length; i++) {
    let idx = remainIndex[i];
    let parent = findParent(res[idx].traceInfo);

    if (!parent) {
      remainIndexNext.push(idx);
    }
  }
  remainIndex = remainIndexNext;
}

function findParent(item) {
  let parent = null;
  for (var i = 0; i < result.length; i++) {
    let row = result[i];
    if (row.name === item.node4.traceId) {
      row.children.push({
        name: item.node5.traceId,
        children: []
      });
      return row;
    } else {
      for (var j = 0; j < row.children.length; j++) {
        let row2 = row.children[j];
        if (row2.name === item.node4.traceId) {
          row2.children.push({
            name: item.node5.traceId,
            children: []
          });
          return row2;
        } else {
          for (var k = 0; k < row2.children.length; k++) {
            let row3 = row2.children[k];
            if (row3.name === item.node4.traceId) {
              row3.children.push({
                name: item.node5.traceId,
                children: []
              });
              return row3;
            } else {
              for (var l = 0; l < row3.children.length; l++) {
                let row4 = row3.children[l];
                if (row4.name === item.node4.traceId) {
                  row4.children.push({
                    name: item.node5.traceId,
                    children: []
                  });
                  return row4;
                } else {
                  for (var n = 0; n < row4.children.length; n++) {
                    let row5 = row4.children[n];
                    if (row5.name === item.node4.traceId) {
                      row5.children.push({
                        name: item.node5.traceId,
                        children: []
                      });
                      return row5;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  return parent;
}

findRoot(res);

while (remainIndex.length) {
  processItems(res);
}
console.log(result);

有来自服务器API的响应数据,称为res。

如果node4和node5 traceId的值相同,则它是结果的根。

node4.traceId-node5.traceId

parent-child

F-G
B-D
B-C
C-E
A-B
E-F
A-A

//result
A-B-C-E-F-G
 -D

您可以在此处检查结果树形图。 https://codesandbox.io/s/10ovv8jvlj

由于要使用react-d3-tree,因此我必须格式化结果格式的数据。

我认为findParent函数不是格式化的好方法。

有很多循环,如果服务器中的数据包含的数据多于当前res的数据,则我必须添加更多的循环。

我想替换为递归函数,但我不知道。

如何更好地修改findParent

1 个答案:

答案 0 :(得分:2)

findParentfindChildren更有意义,更容易编写递归。查找根目录->查找根目录的子项->查找根目录的每个子项-> ...

这是示例代码:

const res = [
  {
    traceInfo: {
      node4: {
        traceId: "F"
      },
      node5: {
        traceId: "G"
      }
    },
    name: "FG"
  },
  {
    traceInfo: {
      node4: {
        traceId: "B"
      },
      node5: {
        traceId: "D"
      }
    },
    name: "BD"
  },
  {
    traceInfo: {
      node4: {
        traceId: "B"
      },
      node5: {
        traceId: "C"
      }
    },
    name: "BC"
  },
  {
    nodeId: "C-E",
    traceInfo: {
      node4: {
        traceId: "C"
      },
      node5: {
        traceId: "E"
      } 
    },
    name: "CE"
  },
  {
    traceInfo: {
      node4: {
        traceId: "A"
      },
      node5: {
        traceId: "B"
      }
    },
    name: "AB"
  },
  {
    traceInfo: {
      node4: {
        traceId: "E"
      },
      node5: {
        traceId: "F"
      }
    },
    name: "EF"
  },
  {
    traceInfo: {
      node4: {
        traceId: "A"
      },
      node5: {
        traceId: "A"
      }
    },
    name: "AA"
  }
];

function processRes(res)
{
  var result = [];
  for(let i = 0; i < res.length ; i++)
  {
    let info = res[i];
    if(info.traceInfo.node4.traceId == info.traceInfo.node5.traceId)
    {
      let root = {name:info.traceInfo.node4.traceId,children:[]};
      findChildren(res.slice(0,i).concat(res.slice(i+1)),root);
      result.push(root);
    }
  }
  return result;
}

function findChildren(res,parent)
{
  for(let i = 0; i < res.length ; i++)
  {
    let info = res[i];
    if(info.traceInfo.node4.traceId == parent.name && info.traceInfo.node4.traceId != info.traceInfo.node5.traceId)
    {
      let node = {name:info.traceInfo.node5.traceId,children:[]};
      findChildren(res.slice(0,i).concat(res.slice(i+1)),node);
      parent.children.push(node);
    }
  }
}

console.log(processRes(res));