array_diff 返回第一个数组中存在但后续所有数组均不存在的值,严格按值比较(不转换类型),保留原始键名,不递归处理嵌套结构。

array_diff 比较两个数组时,只看值不看键
它返回第一个数组中存在、但后续所有数组里都不存在的值,结果保留原始键名。注意:比较是严格按值(string 类型对比),不转换类型,"1" 和 1 被视为不同。
常见错误是以为它会按索引对齐比较,其实完全不会——array_diff 只做「集合差」,不是「逐位差」:
- 如果想比键+值,该用
array_diff_assoc - 如果想忽略大小写比字符串值,得先用
array_map('strtolower', $arr)预处理 - 空字符串
""、0、false在松散比较下易混淆,但array_diff是严格值比较,所以0 !== "",它们不会互相抵消
传入多个数组时,只有第一个数组的元素会被返回
array_diff($a, $b, $c, $d) 的结果永远是「在 $a 里,但不在 $b、$c、$d 中任何一个里的值」。后几个数组只是“排除列表”,自身结构和键名全被忽略。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 别把要查的数组放错位置——比如想查哪些用户在 A 表有、B 表没有,就该写
array_diff($users_in_a, $users_in_b),反了就全空 - 可以传入任意数量数组,但性能随数组长度和数量增长明显下降;单个数组超 10 万项时,建议改用数据库
LEFT JOIN或分块处理 - 如果某个参数是
null或非数组,PHP 会报 Warning 并返回null,务必用is_array()防御
遇到嵌套数组或对象直接失效
array_diff 内部用 == 判断相等,而 PHP 中两个数组即使结构相同,== 也只递归比较,但 array_diff 并不递归——它把整个子数组当做一个不可拆解的值。结果就是:array_diff([[1]], [[1]]) 返回 [[1]],因为子数组没被展开比。
解决方法取决于场景:
- 要深度比较扁平化数据,先用
json_encode()转成字符串再比(注意键序敏感) - 要真正递归差集,得自己写函数,或用
array_udiff配合自定义回调 - 含对象时,
array_diff会直接失败(对象无法转为字符串用于比较),必须提前用get_object_vars()或序列化处理
中文字符、浮点数、NaN 这些容易踩坑
中文本身没问题,但若编码不一致(如 GBK vs UTF-8 字节流),array_diff 会当成不同字符串;浮点数因精度问题,0.1 + 0.2 !== 0.3,导致本该被排除的项残留。
关键细节:
-
NAN和任何值(包括自身)用==都是false,所以含NAN的数组参与array_diff时,它几乎总被保留下来 - 时间戳整数、UUID 字符串这类唯一标识,用
array_diff安全;但价格、评分等浮点字段,建议先round($val, 2)统一精度再比 - 多字节字符排序依赖 locale,但
array_diff不排序,所以只要编码统一,就不会出乱码问题
真正麻烦的是混合类型数组里混着数字字符串和整数——看着一样,array_diff 却不认,这种隐式类型差异最难调试。



















