如果值在数组中的某个位置,in_array($needle, $haystack) 返回 true,否则返回 false。第三个参数传 true,即 in_array($needle, $haystack, true),可以同时要求类型相同;默认就应该使用这种严格写法。
in_array() 只检查值。要检查某个键是否存在,请用 array_key_exists() 或 isset()。
strict 参数
不传第三个参数时,in_array() 使用 == 比较,会在比较前转换类型。传入 true 时,它使用 === 比较:值和类型都必须一致。只要数组中混有数字和字符串,区别就会显现出来,而来自表单、URL 和 CSV 文件的数据经常是这样。
下表中的每个单元格是 PHP 8.3 中这对值用 == 和 === 比较的结果。在你使用的模式下,只要要查找的值和任意一个元素在表中得到 true,in_array() 就返回 true。切换标签页,看看 null、true 和数字字符串那几行。
| $a == $b | true | false | null | 0 | 1 | "0" | "1" | "" | "abc" | "10" | "1e1" | 10 | [] |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| true | |||||||||||||
| false | |||||||||||||
| null | |||||||||||||
| 0 | |||||||||||||
| 1 | |||||||||||||
| "0" | |||||||||||||
| "1" | |||||||||||||
| "" | |||||||||||||
| "abc" | |||||||||||||
| "10" | |||||||||||||
| "1e1" | |||||||||||||
| 10 | |||||||||||||
| [] |
PHP 8 改变了一条规则:非数字字符串不再等于 0,所以 in_array('abc', [0]) 如今是 false,而在 PHP 7 中是 true。为 PHP 7 写的代码有时会依赖这一点,这也是应该传 true、不依赖类型转换规则的又一个理由。比较运算符页面对这些规则有完整的讲解。
不区分大小写的 in_array
in_array() 精确比较字符串,所以 'PHP' 和 'php' 是不同的。检查之前,先把要查找的值和数组都转成小写。mb_strtolower() 还能处理带重音的字母和非拉丁字母。
一次检查多个值
in_array() 只接收一个要查找的值。如果有多个,就把数组当作集合来比较:array_diff() 返回缺少的那些值,所以结果为空就表示全部存在;array_intersect() 返回找到的那些值。
array_diff() 和 array_intersect() 按字符串比较值,所以在这里 1 和 '1' 被视为相等。
在多维数组中使用 in_array
in_array() 不会在嵌套数组内部搜索。要检查是否有某一行的某个字段等于给定值,先用 array_column() 把这个字段提取出来,再在这个一维列表中搜索。
最后一行说明要查找的值本身也可以是数组:它会匹配完全相同的一行,即键、值和顺序都相同。
in_array、array_search 和 isset 的区别
三者都能回答“它在不在里面?”,但返回的内容不同,运行速度也不同:
| 调用 | 返回值 | 在大数组上的速度 |
|---|---|---|
in_array($v, $arr, true) | true 或 false | 扫描每个元素 |
array_search($v, $arr, true) | 键,或 false | 扫描每个元素 |
isset($set[$v]) | true 或 false | 一次哈希查找 |
需要知道值在哪个位置时,用 array_search()。如果要拿许多值和同一个大列表比对,就先把列表翻转一次,让它的值变成键,然后用 isset()。
每次运行的时间都会不同,但差距不会变:isset() 查找的耗时保持不变,而 in_array() 的耗时随列表大小增长。array_flip() 只适用于字符串和整数值,重复的值会合并成一个键,但这对判断是否存在没有影响。
常见问题
in_array 的第三个参数有什么作用?
它开启严格比较。in_array($x, $arr, true) 使用 === 比较,所以不仅值要相同,类型也必须一致:in_array('1', [1, 2], true) 返回 false。不传这个参数时,PHP 使用 == 比较,并会先转换类型。
使用 in_array 时应该总是开启严格模式吗?
通常应该。宽松模式下,in_array(null, [0])、in_array(true, ['any string']) 和 in_array('1e1', ['10']) 都会返回 true。只有当你有意让表单传来的 '5' 匹配整数 5 时,才不开启它。
怎么让 in_array 不区分大小写?
把两边都转成小写:in_array(strtolower($needle), array_map('strtolower', $haystack), true)。如果文本可能包含非 ASCII 字母,就用 mb_strtolower。
怎么判断多个值是否都在数组中?
如果要求全部存在,就检查是否有剩余:!array_diff($needles, $haystack)。如果只要求至少有一个存在,就检查是否有交集:(bool) array_intersect($needles, $haystack)。
in_array 慢吗?
它会逐个元素扫描数组,所以对大数组反复检查时会很慢。先用 $set = array_flip($haystack); 把数组翻转一次,再用 isset($set[$value]) 检查,这只需要一次哈希查找。