递归排序未知深度多维数组的position列并保留键
递归按position排序多维数组问题
问题说明
需要递归对多维数组的每一层级(存在children节点时)按position字段排序,数组结构可变,children节点可能存在或不存在。尝试使用usort未得到预期结果,且因结构限制无法使用嵌套集方案。
原数组
[ 2 => [ 'position' => 0, 'children' => [ 3 => ['position' => "375"], 5 => ['position' => "44"], 6 => ['position' => "567"], 9 => [ 'position' => "12", 'children' => [ 74 => ['position' => "2"], 76 => ['position' => "3"], 77 => ['position' => "1"], ] ], 62 => ['position' => "34"], 63 => ['position' => "11"], 66 => ['position' => "114"], 74 => ['position' => "912"], 76 => ['position' => "4564"], ] ] ]
期望排序结果
[ 2 => [ 'position' => 0, 'children' => [ 63 => ['position' => "11"], 9 => [ 'position' => "12", 'children' => [ 77 => ['position' => "1"], 74 => ['position' => "2"], 76 => ['position' => "3"], ] ], 62 => ['position' => "34"], 5 => ['position' => "44"], 66 => ['position' => "114"], 3 => ['position' => "375"], 6 => ['position' => "567"], 74 => ['position' => "912"], 76 => ['position' => "4564"], ] ] ]
尝试的错误代码
public function recur($data){ // ... foreach($data as $key=>$value){ if (array_key_exists('children', $value)) { usort($value, function ($a, $b): int { if ($a['position'] === $b['position']) { // .... } return $a['position'] <=> $b['position']; }); } } }
问题分析与解决方案
错误代码存在三个核心问题:
usort不保留关联键名:children是带自定义键的关联数组,usort会重置为索引数组,应该用uasort保留原键。- 未递归处理子节点:只排序了当前层级的
children,但children内的元素如果还有自己的children,没有继续递归处理。 - 字符串比较逻辑问题:
position字段是字符串类型,直接用太空船运算符会按字符串排序(比如"2"和"11"字符串排序会出错),需转为整数比较。 - 值传递未修改原数组:遍历中用
$value是值拷贝,修改后不会同步到原数组,需用引用或重新赋值。
正确的递归排序函数
public function sortByPositionRecursive(&$data) { foreach ($data as &$item) { // 如果当前元素有children,先排序children if (isset($item['children']) && is_array($item['children'])) { // 用uasort保留原键名,按position整数排序 uasort($item['children'], function($a, $b) { return (int)$a['position'] <=> (int)$b['position']; }); // 递归处理children里的每个子元素 $this->sortByPositionRecursive($item['children']); } } // 释放引用避免后续问题 unset($item); }
使用示例
// 原数组 $originalArray = [ 2 => [ 'position' => 0, 'children' => [ 3 => ['position' => "375"], 5 => ['position' => "44"], 6 => ['position' => "567"], 9 => [ 'position' => "12", 'children' => [ 74 => ['position' => "2"], 76 => ['position' => "3"], 77 => ['position' => "1"], ] ], 62 => ['position' => "34"], 63 => ['position' => "11"], 66 => ['position' => "114"], 74 => ['position' => "912"], 76 => ['position' => "4564"], ] ] ]; // 调用排序函数 $this->sortByPositionRecursive($originalArray); // 输出结果即为期望的排序后数组 print_r($originalArray);
说明
- 函数参数使用引用传递
&$data,确保直接修改原数组,无需返回值。 uasort保证排序后保留原数组的键名(比如63、9这些自定义键)。- 将
position转为整数比较,避免字符串排序的逻辑错误。 - 递归调用处理每个层级的
children,实现全层级排序。
内容的提问来源于stack exchange,提问作者TheTom
相关产品推荐
相关产品推荐

