php函数无限级和引用传值无穷无尽级

原创
小哥 3年前 (2022-11-02) 阅读数 72 #PHP
文章标签 PHP

<?php
$array = array(
array(id => 1, pid => 0, name => 河北省),
array(id => 2, pid => 0, name => 北京市),
array(id => 3, pid => 1, name => 邯郸市),
array(id => 4, pid => 2, name => 朝阳区),
array(id => 5, pid => 2, name => 通州区),
array(id => 6, pid => 4, name => 望京),
array(id => 7, pid => 4, name => 酒仙桥),
array(id => 8, pid => 3, name => 永年区),
array(id => 9, pid => 1, name => 武安市),
);

/**

  • 无限极点分类的递归实现
  • @param $array 分类数据
  • @param $pid 父ID
  • @param $level 分类级别
  • @return $list 一组类 直接遍历 $level可用于遍历缩进
    */

function getTree($array, $pid =0, $level = 0){

//声明静态数组,避免递归调用,多个声明导致数组重写
static $list = [];
foreach ($array as $key => $value){
//第一次遍历,查找其父节点是根节点的节点。 也就是pid=0的节点
if ($value[pid] == $pid){
//父节点是根节点的节点。,级别为0,也就是第一个层次
$value[level] = $level;
//将数组放入list中
$list[] = $value;
//从阵列中删除此节点,减少后续递归消耗
unset($array[$key]);
//开始递归,查找父ID为该节点ID的节点,标高是原始标高。+1
getTree($array, $value[id], $level+1);

}
}
return $list;
}

/*

  • 获取递归数据,遍历生成分类
    */
    $array = getTree($array);

foreach($array as $value){
echo str_repeat(--, $value[level]), $value[name].
;
}

/****/
//引用算法
function generateTree($array){
//第一步 构造数据
$items = array();
foreach($array as $value){
$items[$value[id]] = $value;
}
//第二部 遍历数据 生成树结构
$tree = array();
foreach($items as $key => $item){
if(isset($items[$item[pid]])){
$items[$item[pid]][son][] = &$items[$key];
}else{
$tree[] = &$items[$key];
}
}
return $tree;
}

//在第一步之后 数据是这样的
Array
(
[1] => Array
(
[id] => 1
[pid] => 0
[name] => 河北省
[children] => Array
(
)

)

[2] => Array
(
[id] => 2
[pid] => 0
[name] => 北京市
[children] => Array
(
)

)

[3] => Array
(
[id] => 3
[pid] => 1
[name] => 邯郸市
[children] => Array
(
)

)

[4] => Array
(
[id] => 4
[pid] => 2
[name] => 朝阳区
[children] => Array
(
)

)

[5] => Array
(
[id] => 5
[pid] => 2
[name] => 通州区
[children] => Array
(
)

)

[6] => Array
(
[id] => 6
[pid] => 4
[name] => 望京
[children] => Array
(
)

)

[7] => Array
(
[id] => 7
[pid] => 4
[name] => 酒仙桥
[children] => Array
(
)

)

[8] => Array
(
[id] => 8
[pid] => 3
[name] => 永年区
[children] => Array
(
)

)

[9] => Array
(
[id] => 9
[pid] => 1
[name] => 武安市
[children] => Array
(
)

)

)

//第一步很容易理解,也就是构造数据。现在我们来仔细谈谈第二步。
$tree = array();
//遍历构造的数据
foreach($items as $key => $item){
//如果pid该节点已存在
if(isset($items[$value[pid]])){
//把当前的$value放到pid节点的son中 注意 这里传递的是一个引用 为什么?
$items[$item[pid]][son][] = &$items[$key];
}else{
$tree[] = &$items[$key];
}
}

//这种方法的核心是引用,php变量传递值的默认方式是按值传递。
//也就是说 假如说 遍历顺序为 河北省 邯郸市 横穿河北省时 将把河北省纳入tree中 当穿越到邯郸时 邯郸市将被纳入河北省子节点阵列 但是!
//这会儿的tree数组中 河北省已经投入使用 根据php变量按值传递的规则 你一点都没变tree数组中的河北省数据 所以这里使用的是引用传递。
//当您对河北省进行更改时,tree河北省在这一阵列中也做出了改变。 让我们做个实验吧 让我们删除引用过程并查看结果。

//使用普通转移值输出结果
Array
(
[0] => Array
(
[id] => 1
[pid] => 0
[name] => 河北省
)

[1] => Array
(
[id] => 2
[pid] => 0
[name] => 北京市
)

)
//可以看到 只有河北省和北京市出口 因为它们是第一级节点 而且排行1和2,放到$tree在数组之后,不传递任何引用,
//则其两个子节点上的后续操作不在$tree现在让我们改变一下顺序。 让邯郸市走在河北省前面 所以根据我们的推断 那么邯郸市应该会出现在tree数组里

//河北省邯郸市产出成果排名前列
Array
(
[0] => Array
(
[id] => 1
[pid] => 0
[name] => 河北省
[son] => Array
(
[0] => Array
(
[id] => 3
[pid] => 1
[name] => 邯郸市
)

)

)

[1] => Array
(
[id] => 2
[pid] => 0
[name] => 北京市
)

)

//这是真的 然后证明我们的推论是正确的 现在,让我们将引用值改回。 再看一下

//使用参考值输出结果
Array
(
[1] => Array
(
[id] => 1
[pid] => 0
[name] => 河北省
[children] => Array
(
[0] => Array
(
[id] => 3
[pid] => 1
[name] => 邯郸市
[children] => Array
(
[0] => Array
(
[id] => 8
[pid] => 3
[name] => 永年区
)

)

)

[1] => Array
(
[id] => 9
[pid] => 1
[name] => 武安市
)

)

)

[2] => Array
(
[id] => 2
[pid] => 0
[name] => 北京市
[children] => Array
(
[0] => Array
(
[id] => 4
[pid] => 2
[name] => 朝阳区
[children] => Array
(
[0] => Array
(
[id] => 6
[pid] => 4
[name] => 望京
)

[1] => Array
(
[id] => 7
[pid] => 4
[name] => 酒仙桥
)

)

)

[1] => Array
(
[id] => 5
[pid] => 2
[name] => 通州区
)

)

)

)
//树结构是完美的输出。 这种方法的核心是引用价值。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门