PHP中合并未知键与深度的多维数组并去除重复元素的方法
解决多维数组合并并去重的问题(未知键名和深度)
你的问题很典型——PHP自带的数组合并函数在处理未知深度的多维数组+子元素去重时确实不太好用,咱们来一步步解决:
为什么现有方法失效?
array_merge_recursive:只会递归合并同键的数组,但不会检查子元素是否重复,所以会保留两个{"ort": "rom", "lioc": "inrom"}array_merge + array_unique:因为两个数组的外层键都是hotels,array_merge会直接用第二个数组的hotels覆盖第一个的,之后再去重也救不回丢失的元素,这就是result2只剩两个元素的原因
自定义递归合并去重函数
我们需要写一个递归函数,既能处理任意深度的数组,又能对列表型的子数组(索引数组)去重。核心思路是:
- 递归遍历两个数组,合并所有键值对
- 遇到列表型数组(键为连续数字)时,将子元素序列化为字符串作为临时键,利用数组键的唯一性去重,再转回原数组格式
代码实现:
function merge_unique_recursive($arr1, $arr2) { $merged = $arr1; foreach ($arr2 as $key => $value) { // 递归处理嵌套数组 if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) { $merged[$key] = merge_unique_recursive($merged[$key], $value); } else { // 列表型数组的元素直接追加 if (is_numeric($key)) { $merged[] = $value; } else { // 关联数组的键直接赋值(如需保留两边关联数组键值,可在此处再递归) $merged[$key] = $value; } } } // 判断是否为列表型数组,若是则去重 if (array_keys($merged) === range(0, count($merged) - 1)) { $temp = []; foreach ($merged as $item) { // 用JSON序列化作为临时键,确保子数组完全相同时才去重 $temp[json_encode($item)] = $item; } // 重置索引,转回列表型数组 $merged = array_values($temp); } return $merged; }
测试你的案例
把你的测试代码替换成下面的调用:
$test_1 = ' { "hotels" : { "hotel" : [ { "ort": "rom", "lioc": "inrom" }, { "ort": "paris", "lioc": "inpsrisd" }, { "ort": "berlin", "lioc": "inberlin" }, { "ort": "milano", "lioc": "inmilano" }, { "ort": "paris", "lioc": "anotherinpsrisd" }, { "ort": "muc", "lioc": "inmuc" } ] } } '; $test_2 = ' { "hotels" : { "hotel" : [ { "ort": "rom", "lioc": "inrom" }, { "ort": "beijing", "lioc": "wanda" } ] } } '; $arr_test1 = json_decode($test_1, TRUE); $arr_test2 = json_decode($test_2, TRUE); $final_result = merge_unique_recursive($arr_test1, $arr_test2); var_dump(json_encode($final_result));
运行后就能得到你想要的预期结果:
{ "hotels" : { "hotel" : [ { "ort": "rom", "lioc": "inrom" }, { "ort": "paris", "lioc": "inpsrisd" }, { "ort": "berlin", "lioc": "inberlin" }, { "ort": "milano", "lioc": "inmilano" }, { "ort": "paris", "lioc": "anotherinpsrisd" }, { "ort": "muc", "lioc": "inmuc" }, { "ort": "beijing", "lioc": "wanda" } ] } }
补充说明
这个函数可以适配任意深度的数组,不管键名是什么:
- 对于关联数组(字符串键):会递归合并对应键的子数组
- 对于列表型数组(数字键):会合并所有元素并去重,完全相同的子数组只会保留一个
内容的提问来源于stack exchange,提问作者Web Star
相关产品推荐
相关产品推荐

