PHP中array_uintersect处理首项为子数组的数组时交集计算异常问题
问题原因分析
首先明确array_uintersect的运行机制和常规理解有偏差:它不会把第一个数组的每一项和第二个数组的所有项逐一比对匹配,而是分为两步执行:
- 先用传入的自定义比较函数,对所有参与交集计算的数组分别做内部排序
- 排序完成后,用双指针线性遍历两个已排序数组,匹配相同元素得到最终交集
你遇到的异常结果,核心是编写的compare2D函数不符合PHP要求的自定义比较函数规则:
- 比较函数必须满足对称性要求:
compare(a,b) = -compare(b,a),如果a > b返回正数,a < b返回负数,相等返回0 - 你的实现中除了相等的情况返回0,其余所有情况都只返回1,没有返回负数的逻辑,会导致排序结果完全不可预期,完全依赖PHP内部排序的实现细节
当你把第二个数组的子数组放在首项时,错误的比较逻辑输出的排序结果刚好让后续线性扫描阶段漏掉了REMOTE元素;把子数组移到非首项位置时,排序结果刚好符合预期,就能得到你要的输出,本质上这两种情况的运行结果都是不稳定的,只是刚好巧合出现了符合预期的结果。
修复建议
你的需求是「判断第一个数组的元素,是否和第二个数组的元素匹配(第二个数组元素是子数组的话判断是否在子数组内,是字符串的话直接判断相等)」,这种非标准的交集匹配逻辑不适合用array_uintersect实现,直接手写遍历逻辑更可靠:
function customIntersect($topics, $arr) { $result = []; foreach ($topics as $topic) { $matched = false; foreach ($arr as $item) { if (is_array($item)) { if (in_array($topic, $item)) { $matched = true; break; } } else { if ($topic === $item) { $matched = true; break; } } } if ($matched) { $result[] = $topic; } } return $result; }
调用这个函数就能稳定得到预期的交集结果,不会受数组元素顺序的影响。
内容的提问来源于stack exchange,提问作者Scott Anderson
相关产品推荐
相关产品推荐

