为给定 CSV 文件生成 baum 层次结构的代码的灵活性

Flexibility for a code to generate baum hierarchy for a given CSV file

我需要借助 Baum 层次结构生成库将 CSV 文件的内容转换为我网站的层次结构...

以下是 CSV 文件的格式,用户将上传该文件以解析到 Baum Hierarchy。其中的列表示层次结构级别。 CSV File Screenshot

现在我已将此 CSV 文件解析为二维数组 ($companyDetailsIn2dArray),我编写的代码仅支持生成到第 3 级,我希望它是 "flexible for any level",即对于更多级别比 3 现在这样做,我写的代码鼓励我为它编写递归函数,但我很困惑,我应该从哪里开始。我用于存储最后创建的节点的临时变量($lastDeptNodeI; $lastDeptNodeJ; $lastMacNodeI; $lastMacNodeJ)限制了我编写递归函数...

请帮助我编写递归函数或建议我使用 CSV 文件获取 Baum 层次结构的任何其他方法...

以下是我的代码...

$lastDeptNodeI =-1; //variable used to store array location(row) for last created 1st level node i.e. Dept node
$lastDeptNodeJ =-1; //variable used to store array location(column) for last created 1st level node i.e. Dept node
$lastMacNodeI =-1; //variable used to store array location(row) for last created 2nd level node i.e. Machine node
$lastMacNodeJ =-1; //variable used to store array location(column) for last created 2nd level node i.e. Machine node
$root = Company::create(['name' => $newCompanyName]);   //Creating node
$root->makeRoot();  //Making Root Node
for($i=0;$i<sizeof($companyDetailsIn2dArray);$i++){
    for($j=0;$j<sizeof($companyDetailsIn2dArray[$i]);$j++){
        if($companyDetailsIn2dArray[$i][$j] != "") {
            if ($j == 0) {  //if it is Dept!
                $newNode[$i][$j] = Company::create(['name' => $companyDetailsIn2dArray[$i]{$j}]);
                $newNode[$i][$j]->makeChildOf($root);
                $lastDeptNodeI = $i;
                $lastDeptNodeJ = $j;
                $lastMacNodeI = -1;
                $lastMacNodeJ = -1;
            } elseif ($j == 1) { // if it is machine
                $newNode[$i][$j] = Company::create(['name' => $companyDetailsIn2dArray[$i]{$j}]);
                if($lastDeptNodeI!=-1 || $lastDeptNodeJ!=-1) {
                    $newNode[$i][$j]->makeChildOf($newNode[$lastDeptNodeI][$lastDeptNodeJ]);
                    $lastMacNodeI = $i;
                    $lastMacNodeJ = $j;
                }
                else{
                    $newNode[$i][$j]->makeChildOf($root);
                    $lastMacNodeI = $i;
                    $lastMacNodeJ = $j;
                }
            } elseif ($j == 2)
            { //if it is Meter!
                $newNode[$i][$j] = Company::create(['name' => $companyDetailsIn2dArray[$i]{$j}]);
                if($lastMacNodeI!=-1 || $lastMacNodeJ!=-1){
                    $newNode[$i][$j]->makeChildOf($newNode[$lastMacNodeI][$lastMacNodeJ]);
                }
                elseif($lastDeptNodeI!=-1 || $lastDeptNodeJ!=-1){
                    $newNode[$i][$j]->makeChildOf($newNode[$lastDeptNodeI][$lastDeptNodeJ]);
                    $lastMacNodeI = $i;
                    $lastMacNodeJ = $j;
                }
                else{
                    $newNode[$i][$j]->makeChildOf($root);
                    $lastDeptNodeI = $i;
                    $lastDeptNodeJ = $j;
                    $lastMacNodeI = -1;
                    $lastMacNodeJ = -1;
                }
            }
        }
    }
}
echo "File parsed Successfully!";

我认为您可以通过 depth-first 搜索的方式添加节点,当您找到节点时也添加 children。

如果你想完全递归,你将需要 2 个递归函数:

  1. 第一个是向树添加节点的函数,但是 添加一个节点后,它会找到它的所有 child(向下一级) 节点,并为这些调用自身。

此函数的签名可能如下所示:addNode(parent_node, i_of_current_node, j_of_current_node, content_of_current_node)

当没有children时递归结束

我也会编写一个辅助函数来查找节点的 children。您只需查找与 j_of_current_node 具有相同 j 的下一个 nonempty 单元格,然后从 j_of_current_node + 1 中获取 i_of_current_node 和 i_of_next_node 之间的非空单元格.

  1. 第二个递归函数将读取 companyDetailsIn2dArray 逐列。

这个函数的签名可能是这样的: readColumn(j_of_current_column, i_of_first_node_in_prev_column)

当 j_of_current_column 大于数组的大小时,递归结束。


当您阅读专栏时,您会为每个 none 空单元格调用 addNode 函数,如下所示:addNode($root, $i, $j, $companyDetailsIn2dArray[$i][$j]) addNode 在 root 下创建新节点,找到 children,然后为 child 节点调用自身,如 addNode($newNode, $childI, $childJ , $companyDetailsIn2dArray[$childI][$childJ]).

这样,一旦您阅读了第一列,您就已将文件中的每个节点添加到第一列中第一个 none 空单元格的 $i 下。您通过调用 readColumn(0, i_size_of_array)

来处理第一列

在处理任何后续列(与第一列相同)时,您只会读取它,直到到达前一列中第一个 none 空单元格的 i 为止,因为您已经添加了更高的节点我索引因为那些在上一列中有一个 parent。您通过调用 readColumn(j_of_current_column + 1, i_of_first_node_in_current_column).

来处理第一列之后的列