最直接方案是array_intersect(),但需用!empty()判断交集存在;大数据量时用array_flip()+isset()更高效;查值存在性须用in_array($v,$a,true)或翻转+isset(),禁用array_key_exists();关联数组交集应选array_intersect_assoc()。

用 array_intersect() 最直接,但要注意返回值不是布尔型
PHP 没有原生的 has_intersection() 这类函数,array_intersect() 是最常用的方案,但它返回的是交集数组(值相同且保留第一个数组的键),不是 true/false。所以不能直接 if (array_intersect($a, $b)) —— 空数组是 falsy,但非空数组里如果某个值是 0、'' 或 null,在弱比较下也可能被误判。
正确做法是检查返回结果是否为空数组:
if (!empty(array_intersect($arr1, $arr2))) {
// 有交集
}
-
array_intersect()比较的是值(value),不关心键(key) - 它只检查第一个数组的元素是否在后续数组中存在,顺序和键名不影响结果
- 如果数组很大,
array_intersect()内部会做多次遍历,性能不如哈希预处理方案(见下一条)
大数据量时用 array_flip() + isset() 更快
当其中一个数组很大(比如上万项),而另一个较小,反复调用 in_array() 或依赖 array_intersect() 的全量比对会变慢。更高效的做法是把大数组「翻转」成键值映射,再用 isset() 做 O(1) 查询:
$lookup = array_flip($big_array); // 值 → 键,自动去重
$hasIntersection = false;
foreach ($small_array as $val) {
if (isset($lookup[$val])) {
$hasIntersection = true;
break;
}
}
-
array_flip()会丢弃重复值(只保留最后一次出现的键),但判断交集不需要计数,这反而省事 - 注意:
$val必须能作为合法数组键(即必须是 string 或 integer;float 会转 int,null 变成 '',对象/数组会报 Warning) - 如果小数组里有无法做键的值(如
['a', [], new StdClass]),得退回到in_array($val, $big_array, true),但记得加第三个参数true避免类型隐式转换
array_key_exists() 和 in_array() 别混用场景
有人误以为 array_key_exists() 能查值是否存在——它只查键(key),不是值(value)。想查值是否存在,必须用 in_array() 或前述的翻转+isset() 方案。
立即学习“PHP免费学习笔记(深入)”;
-
in_array($needle, $haystack)默认松散比较:比如in_array(0, ['foo', 'bar'])返回true(因为'foo' == 0是 true) - 务必加第三个参数
true做严格比较:in_array(0, ['foo', 'bar'], true)才安全 -
array_search()也能判断存在性(返回键或false),但比in_array()多一步键查找,没必要
关联数组交集要小心键名和类型
如果两个数组都是关联的,且你想按「键+值」同时匹配,array_intersect_assoc() 才是正解。它要求键名和对应值都相等:
$a = ['x' => 1, 'y' => 2]; $b = ['x' => 1, 'z' => 3]; var_dump(array_intersect_assoc($a, $b)); // ['x' => 1]
-
array_intersect_key()只比较键名,忽略值 -
array_intersect_uassoc()允许自定义键比较函数,但多数情况没必要,增加复杂度 - 所有
array_intersect*函数都不修改原数组,也不保证返回数组的键顺序与任一输入一致(实际通常保持第一个数组的键序)
最容易被忽略的是类型问题:PHP 数组的键如果是字符串数字(如 '1')和整数 1,在 array_flip() 后会被视为同一键,导致意外覆盖。真要处理混合类型数据,得用 foreach + === 手动比对。



















