PHP三维数组去重方法 array_unique使用后仍无效
PHP三维数组跨层级去重实现方案
核心需求匹配逻辑
我们要做的是完全保留原数组的两层外层结构,从数组靠前位置开始,优先保留第一次出现的三级关联元素,过滤掉后续跨二级子数组出现的完全相同的重复值,不随意调整原有索引顺序和层级关系。
原有实现失效的原因
你之前尝试使用的array_unique($accessories, SORT_REGULAR)无法达到预期,核心问题在于:
- 该函数的比对对象是最外层数组的顶层元素,也就是每个完整的二级子数组,根本不会深入到三级元素层面识别跨二级的重复内容
- 函数执行后会重置最外层数组的索引,无法严格保留原数组的层级结构
可落地的实现代码
通用适配版(不依赖业务主键,判断完全相同的元素)
// 记录已经留存过的三级元素标识 $seenItems = []; $filteredResult = []; // 遍历最外层数组,保留原外层索引 foreach ($accessories as $outerIndex => $secondLevelArr) { $currentSecondLevel = []; foreach ($secondLevelArr as $thirdLevelItem) { // 序列化整个三级元素,完全相同的元素序列化结果必然一致 $itemSign = serialize($thirdLevelItem); // 仅留存首次出现的元素 if (!isset($seenItems[$itemSign])) { $seenItems[$itemSign] = true; $currentSecondLevel[] = $thirdLevelItem; } } // 将过滤后的二级子数组按原索引存回结果 $filteredResult[$outerIndex] = $currentSecondLevel; }
这套逻辑的执行效果和你的预期输出完全匹配:
- 第一个二级子数组内的
id_product=12、id_product=14元素都是首次出现,全部保留 - 第二个二级子数组内的
id_product=16是首次出现正常保留,id_product=14的元素已经在前面的子数组中出现过,会被直接过滤,最终结构和示例预期完全一致
性能优化版(适配业务唯一主键场景)
因为示例里的三级元素有92个字段,如果整个数组数据量很大,序列化整个大数组的性能开销会偏高。如果业务上确定id_product是每个商品元素的唯一标识,可以直接拿商品ID做重复判断标记,省去序列化大数组的开销:
$seenItems = []; $filteredResult = []; foreach ($accessories as $outerIndex => $secondLevelArr) { $currentSecondLevel = []; foreach ($secondLevelArr as $thirdLevelItem) { $productId = $thirdLevelItem['id_product']; if (!isset($seenItems[$productId])) { $seenItems[$productId] = true; $currentSecondLevel[] = $thirdLevelItem; } } $filteredResult[$outerIndex] = $currentSecondLevel; }
注意:这套实现遵循「首次出现优先保留」的规则,也就是靠前位置的重复元素不会被后续同值元素覆盖,完全匹配你示例中的去重规则。
内容的提问来源于stack exchange,提问作者Ahmed guesmi
相关产品推荐
相关产品推荐

