数据无限层级分类递归和引用
说到无限极分类,比较常见的做法是在建表的时候,增加一个parnet_id字段用来区别自己所属的分类(是顶级分类还是子分类)
由于展示数据的时候,需要表达出这种所属关系,所以必然要在读取数据的时候进行一系列处理,由此就牵涉到了两种算法
看下未无限极分类之前的数据结构如下(假设这个数组叫$data):
array (size=6)0 =>
array (size=4)
'cat_id' => int 7
'cname' => string 'php' (length=3)
'is_show' => int 1
'parent_id' => int 80
1 =>
array (size=4)
'cat_id' => int 6
'cname' => string 'mysql' (length=5)
'is_show' => int 1
'parent_id' => int 80
2 =>
array (size=4)
'cat_id' => int 74
'cname' => string 'Linux' (length=5)
'is_show' => int 1
'parent_id' => int 80
3 =>
array (size=4)
'cat_id' => int 80
'cname' => string '软件开发' (length=12)
'is_show' => int 1
'parent_id' => int 0
4 =>
array (size=4)
'cat_id' => int 87
'cname' => string '生活随笔' (length=12)
'is_show' => int 1
'parent_id' => int 0
5 =>
array (size=4)
'cat_id' => int 94
'cname' => string '邻居' (length=6)
'is_show' => int 1
'parent_id' => int 0
一、巧妙的引用算法
由于众所周知的原因,递归对资源的消耗是非常大的,实际执行起来效率也很低,所以有了下面的通过引用算法
上代码:
/*** 无限极分类(引用方式)
*@param array $data需要分类的数组
*@return array 返回一个已经无限极分类完成的数组
*/
function getTree($data)
{
$items = array();
//构建一个新的数组 新数组的key值是自己的主键id值(我这里表的主键是cat_id)
//为何要构建这样一个数组 这就是和下面第二个foreach有关了,看了代码后就会明白何为巧妙引用了
foreach($data as $v)
{
$items[$v['cat_id']] = $v;
}
$tree = array();
//将数据进行无限极分类
foreach($items as $key => $val)
{
if(isset($items[$val['parent_id']]))
{
//关键是看这个判断,是顶级分类就给$tree,不是的话继续拼凑子分类(结合上述&用法)
$items[ $val['parent_id'] ] ['child'] [] = &$items[$key];
}
else
{
$tree[] = &$items[$key];
}
}
//返回无限极分类后的数据
return $tree;
}
上面代码中第一个foreach之后 $items数组变成如下结构:
array (size=6)7 =>
array (size=4)
'cat_id' => int 7
'cname' => string 'php' (length=3)
'is_show' => int 1
'parent_id' => int 80
6 =>
array (size=4)
'cat_id' => int 6
'cname' => string 'mysql' (length=5)
'is_show' => int 1
'parent_id' => int 80
74 =>
array (size=4)
'cat_id' => int 74
'cname' => string 'Linux' (length=5)
'is_show' => int 1
'parent_id' => int 80
80 =>
array (size=4)
'cat_id' => int 80
'cname' => string '软件开发' (length=12)
'is_show' => int 1
'parent_id' => int 0
87 =>
array (size=4)
'cat_id' => int 87
'cname' => string '生活随笔' (length=12)
'is_show' => int 1
'parent_id' => int 0
94 =>
array (size=4)
'cat_id' => int 94
'cname' => string '邻居' (length=6)
'is_show' => int 1
'parent_id' => int 0
第二个foreach之后 $tree数组变成如下结构:
array (size=3)0 =>
array (size=5)
'cat_id' => int 80
'cname' => string '软件开发' (length=12)
'is_show' => int 1
'parent_id' => int 0
'child' =>
array (size=3)
0 =>
array (size=4)
'cat_id' => int 7
'cname' => string 'php' (length=3)
'is_show' => int 1
'parent_id' => int 80
1 =>
array (size=4)
'cat_id' => int 6
'cname' => string 'mysql' (length=5)
'is_show' => int 1
'parent_id' => int 80
2 =>
array (size=4)
'cat_id' => int 74
'cname' => string 'Linux' (length=5)
'is_show' => int 1
'parent_id' => int 80
1 =>
array (size=4)
'cat_id' => int 87
'cname' => string '生活随笔' (length=12)
'is_show' => int 1
'parent_id' => int 0
2 =>
array (size=4)
'cat_id' => int 94
'cname' => string '邻居' (length=6)
'is_show' => int 1
'parent_id' => int 0
二、国民级算法-递归
从数据库取得二维数组省略,递归的思路其实很简单,遍历数组,根据每条数据的id值去寻找所有parent_id值等于自己id值的数据,直到找不到为止。
好了 上代码:
/*** 无限极分类(递归方式)
*@param array $categoryies 需要分类的数组
*@param int $parent_id 需要查询的顶级分类id,默认为0 表示顶级分类
*@param int $level 默认0 表示是顶级分类 增加无限极分类的层级标识 用于在模板显示缩进层级关系
*@return array 返回一个已经无限极分类完成的数组
*/
function limit_category($categoryies, $parent_id = 0, $level = 0)
{
//定义一个静态数组 用于保存每次遍历得到的结果
static $res = [];
//遍历数组 进行数据判断
foreach($categoryies as $key => $val)
{
if($val['parent_id'] == $parent_id)
{
$val['level'] = $level;
//是要找的父级分类内容
$res[] = $val;
//递归点 当前分类有可能有子分类
limit_category($categoryies, $val['cat_id'], $level + 1); //注意这里是cat_id不是parent_id !!
}
}
return $res;
}
//调用:
limit_category($data);
最后返回的数组结构如下:
array (size=6)0 =>
array (size=5)
'cat_id' => int 80
'cname' => string '软件开发' (length=12)
'is_show' => int 1
'parent_id' => int 0
'level' => int 0
1 =>
array (size=5)
'cat_id' => int 7
'cname' => string 'php' (length=3)
'is_show' => int 1
'parent_id' => int 80
'level' => int 1
2 =>
array (size=5)
'cat_id' => int 6
'cname' => string 'mysql' (length=5)
'is_show' => int 1
'parent_id' => int 80
'level' => int 1
3 =>
array (size=5)
'cat_id' => int 74
'cname' => string 'Linux' (length=5)
'is_show' => int 1
'parent_id' => int 80
'level' => int 1
4 =>
array (size=5)
'cat_id' => int 87
'cname' => string '生活随笔' (length=12)
'is_show' => int 1
'parent_id' => int 0
'level' => int 0
5 =>
array (size=5)
'cat_id' => int 94
'cname' => string '邻居' (length=6)
'is_show' => int 1
'parent_id' => int 0
'level' => int 0
数据量不大的话 两种方式执行起来速度相差无几,数据量大的话,引用方式秒杀递归方式,无论是从性能速度还是内存占用空间大小
以上是 数据无限层级分类递归和引用 的全部内容, 来源链接: utcz.com/a/123317.html