php-ml自动分类,PHP实现无限级分类(递归+引用)

本文探讨了如何使用递归和引用优化数据结构,特别是处理数据库原始数据的层次结构。通过重新排列数据并利用引用,可以高效地获取每个节点的子孙信息,避免了多次循环。文中通过示例代码详细解释了这一过程,并对比了赋值与赋址的区别,强调了引用在处理递归数据结构时的重要性。
摘要由CSDN通过智能技术生成

原始数据

数据库

0fbe2f982a03

原始数据

打印到页面

0fbe2f982a03

原始数据

递归

递归的思路就是【找儿子】,也就是循环所有数据,找到每条数据的所有儿子、儿子的儿子、儿子的儿子的儿子....,首先我们知道要找test1的儿子就是找所有pid为1的数据,于是遍历整个数组找到了test1-1和test1-2;然后还要分别找test1-1和test1-2的儿子,就这样一直找下去,由于每次找儿子的方法都是一样的,就是遍历所有数据(除开自己的长辈,因为长辈不可能是儿孙),找出符合条件的,唯一不同的就是每次找儿子的爹不一样,代码如下:

function getChild($data, $id = 0)

{

//初始化儿子

$child = [];

//循环所有数据找$id的儿子

foreach ($data as $key => $datum) {

//找到儿子了

if ($datum['pid'] == $id) {

//保存下来,然后继续找儿子的儿子

$child[$datum['id']] = $datum;

//先去掉自己,自己不可能是自己的儿孙

unset($data[$key]);

//递归找,并把找到的儿子放到一个child的字段中

$child[$datum['id']]['child'] = $this->getChild($data, $datum['id']);

}

}

return $child;

}

运行结果:

0fbe2f982a03

递归运行结果

引用

引用确实是一个非常巧妙的方法,也不用像递归那样循环那么多次,思路就是首先把所有数据以id为索引重新排列,排列之后长这个样子:

0fbe2f982a03

重排之后的数据

然后重点来啦!!!然后只需要找到根节点,也就是pid是0的三条数据,把它们放到一个全新的数组中,注意:这里的放并不是简单的赋值,而是引用之前的地址。这两者有什么不同呢,这里简单几个例子说明一下:

function test(){

$a=1;

$b=$a; //赋值

$b1=&$a;//赋址

$a=2;

dump('$b的值是:'.$b);

dump('$b1的值是:'.$b1);

}

最开始$a初始化为1,把$a的值(也就是1)赋给变量$b,然后把$a的地址(内存地址)赋给$b1,然后改变$a的值,再查看$b和$b的值。结果如下:

0fbe2f982a03

传值和传址的区别

我们发现$b的值还是1,而$b1的值却跟随着$a的改变而改变了,这就是因为$b保存的是$a的地址,无论$a怎么变他们的值都会保持一致。

回到我们之前的问题上来,我们用新的数组保存了根节点的地址,后面无论根节点怎么变我们的新数组都会和变化过后的数据保持一致;那么不是根节点的数据怎么处理呢,我们这里可以把它的地址放到他爹的儿子节点当中,这样的话就是一层层引用,最后所有的数据都被新数组引用了。

说了这么多,代码如下:

function getChild($data)

{

$tree = [];

$newData = [];

//循环重新排列

foreach ($data as $datum) {

$newData[$datum['id']] = $datum;

}

foreach ($newData as $key => $datum) {

if ($datum['pid'] > 0) {

//不是根节点的将自己的地址放到父级的child节点

$newData[$datum['pid']]['child'][] = &$newData[$key];

} else {

//根节点直接把地址放到新数组中

$tree[] = &$newData[$datum['id']];

}

}

return $tree;

}

运行结果:

0fbe2f982a03

引用运行结果

参考文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值