PHP按相同ID合并两个多维数组的实现问题
解决按ID合并嵌套数组的问题
我来帮你搞定这个嵌套数组按ID合并的需求!核心问题是要以arr1的结构/顺序为基准,用arr2里对应ID的补充数据填充,同时递归处理所有嵌套的children节点。你之前的代码问题主要出在递归逻辑错误,以及没有高效地通过ID匹配元素,下面是具体的解决思路和代码:
关键思路
- 先构建ID映射表:把arr2转换成以
id为键的关联数组,这样可以O(1)时间找到对应ID的元素,避免每次循环遍历arr2,效率更高,也更清晰。 - 递归填充节点:遍历arr1的每个节点,用ID映射表找到对应的数据补充字段,然后递归处理该节点的
children(如果有的话)。
完整代码实现
function mergeArrays($arr1, $arr2) { // 第一步:构建arr2的ID映射表,快速查找对应ID的元素 $idMap = []; // 辅助函数:递归遍历arr2的所有节点,加入映射表 $buildIdMap = function($items) use (&$idMap, &$buildIdMap) { foreach ($items as $item) { $idMap[$item['id']] = $item; // 递归处理嵌套的children if (isset($item['children']) && is_array($item['children'])) { $buildIdMap($item['children']); } } }; $buildIdMap($arr2); // 第二步:递归处理arr1的节点,填充补充数据 $processNode = function($node) use (&$idMap, &$processNode) { // 匹配对应ID的arr2数据,合并字段(保留arr1原有结构) if (isset($idMap[$node['id']])) { $node = array_merge($node, $idMap[$node['id']]); } // 递归处理当前节点的children if (isset($node['children']) && is_array($node['children'])) { $node['children'] = array_map($processNode, $node['children']); } return $node; }; // 批量处理arr1的所有根节点 return array_map($processNode, $arr1); } // 测试示例数据 $arr1 = [ [ "id" => "24", "children" => [ [ "id" => "21", "children" => [["id" => "15"]] ] ] ] ]; $arr2 = [ ["id" => "24", "name" => " x", "time" => "0", "status" => "0"], [ "id" => "21", "children" => [["id" => "15", "name" => "x", "time" => "0", "status" => "0"]], "name" => "x", "time" => "0", "status" => "0" ] ]; $arr3 = mergeArrays($arr1, $arr2); print_r($arr3);
代码解释
- ID映射表构建:用递归辅助函数
buildIdMap遍历arr2的所有节点(包括嵌套的children),把每个节点按id存入$idMap,后续查找对应ID的元素只需直接取键值,效率大幅提升。 - 递归节点处理:
processNode函数负责单个节点的填充:先合并当前ID对应的arr2数据(array_merge会保留arr1原有结构,同时添加/覆盖arr2的字段),再递归处理该节点的children数组。 - array_map批量处理:用
array_map批量处理arr1的根节点和每个children数组,代码更简洁易读。
你之前代码的问题分析
- 递归调用错误:你之前的递归调用是
merge($arr1, $arr2),这会重新处理整个arr1数组,而非当前节点的children,导致逻辑混乱。 - ID匹配效率低:每次循环遍历arr2找对应ID,数据量大时性能差且容易出错。
- 节点判断不准确:
is_array($value)判断太宽泛,应该专门判断是否存在children键且为数组。
运行上面的代码,就能得到你期望的嵌套完整数据的输出啦!
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

