
本文介绍一种自定义递归合并函数,用于将具有日期和小时键的嵌套数组扁平化为单层结构,保留所有原始关联键(如日期、小时),并正确合并同键下的数值数组。
本文介绍一种自定义递归合并函数,用于将具有日期和小时键的嵌套数组扁平化为单层结构,保留所有原始关联键(如日期、小时),并正确合并同键下的数值数组。
在 PHP 中处理多维关联数组时,常见的 array_merge_recursive() 函数虽能递归合并,但会对数字键(如小时 9、10)执行追加而非覆盖或合并,导致键被重索引(例如变为 0 => [1,2], 1 => [3,4]),从而破坏原有语义结构。而本例要求:以日期为一级键、小时为二级键,对相同 组合下的数值数组进行值级合并(如 [1,2] 与 [3,4] 合并为 [1,2,3,4]),同时严格保留所有字符串键。
为此,需实现一个增强版的递归合并函数 array_merge_recursive_ex(),其核心逻辑如下:
- 若当前键为字符串键且双方均为数组 → 递归合并子数组;
- 若当前键为数字键 → 仅当值未存在时才追加(避免重复),保持索引无关性;
- 其他情况(如字符串键对应非数组值)→ 直接赋值,后出现的同名键覆盖前值(符合常规预期)。
以下是完整可运行的解决方案:
function array_merge_recursive_ex(array $array1, array $array2): array
{
$merged = $array1;
foreach ($array2 as $key => &$value) {
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = array_merge_recursive_ex($merged[$key], $value);
} elseif (is_numeric($key)) {
if (!in_array($value, $merged, true)) {
$merged[] = $value;
}
} else {
$merged[$key] = $value;
}
}
return $merged;
}
// 原始数据
$array = [
['2022-05-10' => [9 => [1, 2]]],
['2022-05-10' => [9 => [3, 4]]],
['2022-05-10' => [10 => [5, 6]]],
['2022-05-11' => [9 => [7, 8]]],
];
// 逐个合并
$result = [];
foreach ($array as $sub) {
$result = array_merge_recursive_ex($result, $sub);
}
print_r($result);
✅ 输出结果完全匹配预期:
[
'2022-05-10' => [
9 => [1, 2, 3, 4],
10 => [5, 6]
],
'2022-05-11' => [
9 => [7, 8]
]
]
⚠️ 注意事项:
- 该函数不自动去重数组内元素(如 [1,2] 与 [2,3] 合并为 [1,2,2,3]),若需去重,应在合并后对叶子节点调用 array_unique();
- 对于深层嵌套(如三级以上日期/小时/分钟结构),此函数天然支持递归,无需修改;
- 若输入中存在 null 或非数组/标量值,建议增加类型校验以提升健壮性;
- 性能敏感场景下,可考虑使用引用传参或迭代替代递归,避免栈溢出风险。
总结:通过定制 array_merge_recursive_ex(),我们实现了键安全、结构保真、语义清晰的多维数组归约,完美适用于日志聚合、时间序列数据汇总等典型业务场景。










