PHP多种方式实现无限级分类
关于无限级分类,这是一个经常用到的知识点,做web开发,绝大多数的情况会使用到它。使用不同的方式实现就会有不一样的性能开销。对于国民级的递归实现方式,这是最简单也是最消耗性能的方式,而使用引用的方式来实现,开销则会小很多。
那么如何去选择?对于分类不多的项目,递归与引用的实现,性能开销相差无几;对于分类很多的项目,推荐使用引用的方式实现。
方式一 array_merge合并数组方式实现
/**
* 方式一 array_merge合并数组方式实现
*
* @param array $data 二维数组,需要递归的数组数据
* @param integer $pid 父ID,默认顶级分类
* @param integer $level 层次
*
* @return array $arrTree 返回值,排序好的二维数组
*/
function makeTreeOne($data , $pid = 0 , $level = 0){
$arrTree = [];
foreach($data as $k => $v){
// 判断是否为上级分类
if($v['parentId'] == $pid){
$v['level'] = $level;
$arrTree[] = $v;
// 此处是重点
// 递归调用查找下级分类,查找时会有返回值,将该返回值赋值给一个新变量
$res = makeTreeOne($data , $v['areaId'] , $level + 1);
// 删除遍历过的数据索引,减少性能开销
unset($data[$k]);
// 合并数组
$arrTree = array_merge($arrTree , $res);
}
}
return $arrTree;
}
方式二 静态变量方式实现
/**
* 方式二 静态变量方式实现
*
* @param array $data 二维数组,需要递归的数组数据
* @param integer $pid 父ID,默认顶级分类
* @param integer $level 层次
*
* @return array $arrTree 返回值,排序好的二维数组
*/
function makeTreeTwo($data , $pid = 0 , $level = 0){
// 此处是重点
static $arrTree = [];
foreach($data as $k => $v){
if($v['parentId'] == $pid){
$v['level'] = $level;
// 使用静态,只会初始化一次,当遍历下一个分类时,保留上一次数据
$arrTree[] = $v;
unset($k);
makeTreeTwo($data , $v['areaId'] , $level + 1);
}
}
return $arrTree;
}
方式三 全局变量方式实现
/**
* 方式三 全局变量方式实现
*
* @param array $data 二维数组,需要递归的数组数据
* @param integer $pid 父ID,默认顶级分类
* @param integer $level 层次
*
* @return array $arrTree 返回值,排序好的二维数组
*/
$tree = [];
function makeTreeThree($data , $pid = 0 , $level = 0){
global $tree;
foreach($data as $k => $v){
if($v['parentId'] == $pid){
$v['level'] = $level;
$tree[] = $v;
makeTreeThree($data , $v['areaId'] , $level + 1);
}
}
return $tree;
}
方式四 引用方式实现(一)
/**
* 方式四 引用方式实现(一)
*
* @param array $data 二维数组,需要递归的数组数据
* @param integer $pid 父ID,默认顶级分类
* @param integer $level 层次
*
* @return array $arrTree 返回值,排序好的二维数组
*/
function makeTreeFour($data , $pid = 0 , $level = 0 , &$tree = []){
foreach($data as $v){
if($v['parentId'] == $pid){
$v['level'] = $level;
$tree[] = $v;
makeTreeFour($data , $v['areaId'] , $level + 1 , $tree);
}
}
return $tree;
}
方式五 引用方式实现(二)【推荐使用】
/**
* 方式五 引用方式实现(二)
*
* @param array $data 二维数组,需要递归的数组数据
* @param integer $pid 父ID,默认顶级分类
* @param integer $level 层次
*
* @return array $arrTree 返回值,多维数组
*/
function makeTreeFive($data , $pid = 0 , $level = 0){
// 存储构造好的数组数据
$indexArray = [];
foreach($data as $k => $v){
$indexArray[$v['areaId']] = $v;
}
// 存储递归整理的数组数据
$tree = [];
foreach($indexArray as $k => $v){
// 判断是否为上级分类
if($v['parentId'] == $pid){
// 顶级分类则将地址存放到数组tree中
$tree[] = &$indexArray[$k];
}else{
// 不是顶级分类,则将地址存放到父级分类的son节点中
$indexArray[$v['parentId']]['son'][] = &$indexArray[$k];
}
}
return $tree;
}
2021-10-14日更新
测试数据为15034条,所用字段为 id、pid、name。
电脑配置:Intel(R) Core(TM) i7-10700 CPU、32G内存、64位系统。
测试结果:推荐使用 方式五。
测试结果对比
测试的结果不太稳定,但是差距不太大。
方式一:所花费时间 11.3940298557秒;
方式二:所花费时间 11.1888649464秒;
方式三:所花费时间 11.2277669907秒,结果输出到浏览器时页面出现崩溃;
方式四:所花费时间 11.2678568363秒,结果输出到浏览器时页面出现崩溃;
方式五:所花费时间 0.0672979355秒。
由此可见,使用方式五的引用方式所花费的时间是最少的,因此,请开始使用它吧。
我是温新,期待和优秀的你一起同行!
夕阳何处寻
2020年03月26日
请登录后再评论