普通方法和递归解决同一个问题的两种思路

in PHP with 0 comment

主要实现把php后端返回的菜单数据组织成树形菜单,供前端调用

后台返回的数据如下[用php数组表示]

$CtrlPerm = [
    [
        "perm_id" => 2,
        "mid" => 1,
        "parent_id" => 0,
        "name" => "homePanel",
        "path" => "/",
        "component" => 'Layout',
        "mtype" => 0,
        "title" => '控制面板',
        "icon" => 'el-icon-s-home',
        "redirect" => "",
        "hidden" => 0,
        "status" => 1,
        "condition" => "",
        "listorder" => 33
    ],
    [
        "perm_id" => 3,
        "mid" => 2,
        "parent_id" => 0,
        "name" => "sysManager",
        "path" => "/sys",
        "component" => 'Layout',
        "mtype" => 0,
        "title" => '系统管理',
        "icon" => 'el-icon-s-tool',
        "redirect" => "/user",
        "hidden" => 0,
        "status" => 1,
        "condition" => "",
        "listorder" => 44
    ],
    [
        "perm_id" => 4,
        "mid" => 3,
        "parent_id" => 2,
        "name" => "userManager",
        "path" => "/sys/user",
        "component" => 'User/User',
        "mtype" => 1,
        "title" => '用户管理',
        "icon" => 'el-icon-s-user',
        "redirect" => "",
        "hidden" => 0,
        "status" => 1,
        "condition" => "",
        "listorder" => 55
    ],
    [
        "perm_id" => 5,
        "mid" => 5,
        "parent_id" => 3,
        "name" => "userDelete",
        "path" => "/user/delete",
        "component" => 'User/delete',
        "mtype" => 2,
        "title" => '删除用户',
        "icon" => 'el-icon-s-delete',
        "redirect" => "",
        "hidden" => 0,
        "status" => 1,
        "condition" => "",
        "listorder" => 66
    ],
    [
        "perm_id" => 9,
        "mid" => 8,
        "parent_id" => 0,
        "name" => "inquiryManager",
        "path" => "/inquiry",
        "component" => 'Inquiry/Inquiry',
        "mtype" => 0,
        "title" => '线索管理',
        "icon" => 'el-icon-s-data',
        "redirect" => "/inquiry/deepblue",
        "hidden" => 0,
        "status" => 1,
        "condition" => "",
        "listorder" => 66
    ],
    [
        "perm_id" => 22,
        "mid" => 9,
        "parent_id" => 8,
        "name" => "inquiryManager",
        "path" => "/inquiry",
        "component" => 'Inquiry/Inquiry',
        "mtype" => 2,
        "title" => '线索添加',
        "icon" => 'el-icon-s-data',
        "redirect" => "/inquiry/deepblue",
        "hidden" => 0,
        "status" => 1,
        "condition" => "",
        "listorder" => 7788
    ]
];

现在是要把当前的数组数据转换成嵌套数组,即把 mid === parent_id的这一个数组挂到 相应parent_id那个元素上,并且要求实现无限挂载,即可能是多级

普通方法【未优化】

function transer_array($data, $pid){
    $treeArray = [];
    foreach($data as $k => $v){
        $meta = [
            "title" => $v["title"],
            "icon" => $v["icon"]
        ];
        $data[$k]["meta"] = $meta;
        unset($data[$k]["title"]);
        unset($data[$k]["icon"]);
        $data[$k]["children"] = [];
        $treeArray[] = $data[$k];
    }

        $findArr = [];
        for($i = count($treeArray) - 1; $i >= 0 ; $i--){
            foreach($treeArray as $k => $v){
                if($v["parent_id"] === $treeArray[$i]["mid"]){
                    $treeArray[$i]["children"][] = $treeArray[$k];
                    $findArr[] = $k;
                    //unset($treeArray[$k]);
                }
            }
        }
        //删除数组中findArr中的元素
        foreach($findArr as $k => $v){
            unset($treeArray[$v]);
        }
   return $treeArray;
}

普通方法即先构造数据,然后挂载子节点,最后删除被挂载过的子节点, 这里注意两次嵌套循环的地方,最外层要从最后一个元素开始遍历,因为挂载的顺序一定要是 孙-->子-->父 这样才行,不然如果先挂载子,然后孙这个节点就挂载不上了。

递归实现方法

递归实现起来代码看着很简洁,实际上要对递归的过程非常熟悉才可以,要对回归条件和递进过程分析的相当清楚才不会出错,这种思路的话 就是直接从父挂载子节点再挂载孙子节点的思路,挂载好后直接返回挂载好的节点,代码如下

function transer_array_recursive($data, $pid){
    $treeArray = [];
    foreach($data as $k => $v){
        if($v["parent_id"] == $pid){
            $meta = [
                "title" => $v["title"],
                "icon" => $v["icon"]
            ];
            $data[$k]["meta"] = $meta;
            unset($data[$k]["title"]);
            unset($data[$k]["icon"]);
            //递归添加其子节点
            $data[$k]["children"] = transer_array_recursive($data, $v["mid"]);
            $treeArray[] = $data[$k];  
        }
        
        //$treeArray[] = $data[$k];
    }
    return $treeArray;
}
评论已关闭.