foreach里面的unset

无限级分类 迭代法查看子孙树

function subtree($arr,$parent){
$subs = array();
$task = array($parent);
while(!empty($task)){
$flag = false; //$flag初始化为假
foreach($arr as $k=>$v){
if($v[‘parent’] == $parent){
$subs[] = $v;
$parent = $v[‘id’];
array_push($task,$v[‘id’]);
unset($arr[$k]); //为什么此处要用unset??????
$flag = true; //找到子栏目
}
}
if($flag == false){
array_pop($task);
$parent = end($task);
}
print_r($task);
}
return $subs;
}

回复讨论(解决方案)

当 foreach 执行过了 $arr[0] 后就销毁 $arr[0],执行了 $arr[1] 后就销毁 $arr[1]

如果不销毁的话 , while 循环执行到下一次时 后面的 foreach($arr as $k=>$v) 有会把$arr从头执行了

执行过的就清除,否则会重复执行。

举个例子就清楚了

$ar = array(
array(‘id’ => 1, ‘parent’] =>0),
array(‘id’ => 2, ‘parent’] =>1),
array(‘id’ => 3, ‘parent’] =>1),
);
subtree($ar, 1);
id=1 的节点有 id=2 和 id=3 的两个子节点

当找到 id=2 的节点后,如果不删去的话,下一轮查找就又会找到 id=2 的节点

从而出现死循环,显然这个 unset($arr[$k]); 是不得已而为之的,因为这个算法的思路有问题(他采用的是 深度优先算法,应该还有优化的余地)

而 广度优先算法 就要简单多了

function subtree($arr,$parent){
$subs = array();
$task = array($parent);
for($i=0;$i$v){
if($v[‘parent’] == $parent){
$subs[] = $v;
if(! in_array($v[‘id’], $task)) $task[] = $v[‘id’];
}
}
}
return $subs;
}

如果不unset,就会重复执行了。

当 foreach 执行过了 $arr[0] 后就销毁 $arr[0],执行了 $arr[1] 后就销毁 $arr[1]

如果不销毁的话 , while 循环执行到下一次时 后面的 foreach($arr as $k=>$v) 有会把$arr从头执行了

还有个问题,为什么要用$arr[$k],而不是$v[$k]

foreach($arr as $k=>$v)

相当于

$arr[$k] = $v;

要删除 $v 就是删除 $arr[$k] 了;

没有$v[$k] 这个。

Posted in 未分类