最稳妥的检测方式是 array_values($arr) === $arr,因其直接验证数组键是否为从0开始的连续整数且值完全一致,避免了字符串数字键、稀疏数组等误判。

怎么快速判断一个PHP数组是不是纯索引数组
直接结论:用 array_values($arr) === $arr 是最稳妥的检测方式,比检查键名类型或用 array_keys 更可靠。
原因很简单:PHP里“索引数组”没有语言级定义,它只是开发者约定俗成的说法——指键为连续数字(从0开始)、且顺序排列的数组。而 array_values 会强制重排键为 0,1,2… 并返回新数组;如果原数组本来就符合这个结构,那重排前后内容和键完全一致,用全等 === 就能精准捕获。
常见错误是只检查 is_numeric(key) 或 !array_keys($arr) === range(0, count($arr)-1),但这些在稀疏数组、键被 unset 过、或含字符串数字键(如 "0")时都会误判。
为什么 array_keys($arr) !== range(0, count($arr)-1) 不靠谱
这个写法看似直观,实际踩坑非常多:
立即学习“PHP免费学习笔记(深入)”;
-
range()返回的是整数键,但array_keys()在遇到字符串数字键(如["0" => "a", "1" => "b"])时也返回字符串,比较结果恒为false,误判为“非索引” - 只要中间某个键被
unset过(比如[0=>'a', 1=>'b', 3=>'c']),range就对不上,哪怕剩下全是数字键 - 空数组
[]下range(0, -1)返回空数组,但某些PHP版本行为不一致,导致比较结果不可靠
array_values($arr) === $arr 的使用边界和注意点
这个判断法简洁有效,但有三个关键前提必须满足:
- 数组值不能包含浮点数、资源、闭包、对象等无法用
===安全比较的类型(否则比较直接失败) - 所有值必须是可序列化且结构一致的(例如嵌套数组的键顺序、引用关系会影响全等结果)
- 不能用于带引用的数组(
&$val),因为array_values会断开引用,导致值相同但引用不同,===返回false
典型安全场景:处理表单提交数据、JSON解码后的数组、数据库查询结果(PDO默认 PDO::FETCH_ASSOC 不适用,但 PDO::FETCH_NUM 可以)。
示例:
$a = [1, 2, 3];<br>var_dump(array_values($a) === $a); // true<br><br>$b = ["a", "b", "c"];<br>var_dump(array_values($b) === $b); // true<br><br>$c = [1 => "x", 2 => "y"];<br>var_dump(array_values($c) === $c); // false(缺键0)
如果数组含不可比较值,该怎么降级判断
当确定数组可能含对象、资源或浮点数时,放弃 ===,改用结构校验:
- 先用
array_keys($arr)拿出所有键,逐个检查是否全为整数且 >= 0 - 再用
count($arr) === max(array_keys($arr)) + 1验证是否连续(空数组要单独处理) - 最后补一句
min(array_keys($arr)) === 0确保从0开始
注意:这种写法性能略差,且仍无法识别字符串数字键(如 ["0"=>"a"]),所以优先推荐第一种方案,仅在明确存在不可比较值时才退而求其次。
真正容易被忽略的是:PHP数组的“索引性”本质是运行时行为,不是类型声明。哪怕你用 array_values 强制转了一次,下一行加个 $arr["foo"] = "bar",它就立刻不再是索引数组了。











