数组转为树状结构中出现的问题

it2023-06-21  61

 今天遇到了一个平时很少遇到的问题。 这是一个将数组转换为树状结构的函数, 主要为了使用部门的无极限分类这样的问题,

递归的方式当然可以解决,但是复杂度太高,不适合,在网上找了一个方法。 因为返回的是json, 结果前端得到就是个对象, 所以要调整为数组。

public function listToTree($list, $root = 0, $pk = 'id', $pid = 'pid', $child = 'children') { $tree = array(); if (is_array($list)) { $refer = array(); foreach ($list as $key => $data) { $refer[$data[$pk]] = &$list[$key]; } foreach ($list as $key => $data) { // 判断是否存在parent $parentId = $data[$pid]; if ($root == $parentId) { $tree[$data[$pk]] = &$list[$key]; } else { if (isset($refer[$parentId])) { $parent = &$refer[$parentId]; $parent[$child][$data[$pk]] = &$list[$key]; } } } } return $tree; }

 

开始的时候,我直接使用的array_values取值。

后来值使用过程中出现了BUG, 有一部分数据不能展示。(我已经排除了其他问题,确定了就是转换树状结构的问题)。

首先要感谢的我头,是他帮助我理解了这个bug.

我们来分析一下,在这个foreach循环中。

主要是这里

$parent = &$refer[$parentId]; $parent[$child][$data[$pk]] = &$list[$key];

第一次进入这个逻辑,那么 $parent[$child] 最后是个数组,因为用了 array_values。如

第二次进入这个逻辑的时候,$parent[$child] 数组被赋了一个指定索引的值。在array_values之前。

第二次,在使用array_values后。

$parent[$child] 里的数组 索引发生了改变, 变为默认的 0、1...

如果第三次数组插入数值,而这个数值的pid刚好是0或者1的话,那么数组原有的0或1就被第三次插入的覆盖了。

这就是为什么部分值会丢失的原因!!!

那么如何修改了?

$parent[$child][$data[$pk]] = &$list[$key]; $parent[$child] = array_values($parent[$child]);

改为

$parent[$child][] = &$list[$key]; //$parent[$child] = array_values($parent[$child]); //不需要了

这里的本来的意图就是把子项放到父项的children里,直接推到数组里既可以了。

这个就是有序数组和无序数组的问题。

所以,如果确认是有序数组就不要操作索引了,容易发生覆盖

最后是我调整后的函数

public function listToTree($list, $root = 0, $pk = 'id', $pid = 'pid', $child = 'children') { $tree = array(); if (is_array($list)) { $refer = array(); foreach ($list as $key => $data) { $refer[$data[$pk]] = &$list[$key]; } foreach ($list as $key => $data) { // 判断是否存在parent $parentId = $data[$pid]; if ($root == $parentId) { $tree[$data[$pk]] = &$list[$key]; } else { if (isset($refer[$parentId])) { $parent = &$refer[$parentId]; $parent[$child][] = &$list[$key]; } } } } return array_values($tree); }

 

最新回复(0)