kkangil
kkangil

Reputation: 1746

How can I replace to recursive function?

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

There is response data from server api called res.

If node4 and node5 traceId values are same, it is root for result.

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

you can check result tree graph here. https://codesandbox.io/s/10ovv8jvlj

And I have to format data like result because of using react-d3-tree.

I think findParent function isn't good way to format.

There are many loops and If the data from server include more than current res data, I have to add more loops.

I want to replace to recursive function but I have no ideas.

How can I modify findParent better way?

Upvotes: 1

Views: 91

Answers (1)

Ricky Mo
Ricky Mo

Reputation: 7718

Instead of findParent, findChildren makes more sense and easy to write recursive. Find the root -> find the children of the root -> find the children of each children of the root ->...

Here is an example code:

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

Upvotes: 2

Related Questions