array_keys的第二个参数用于严格匹配指定值并返回对应键名,不传则返回全部键,传入不存在的值则返回空数组;它无法自动识别重复值,需配合array_count_values等函数实现。

array_keys 的第二个参数是值匹配的开关
array_keys 默认返回所有键名,但加第二个参数就能筛选出对应值的键。它不是“找出相同值”,而是“找出等于某个指定值的所有键”——这点容易误解。比如你有一组重复的 'apple',想拿到所有出现位置的键,就得传 'apple' 进去。
注意:它只做严格相等(===)比较,类型必须一致。如果数组里有 0 和 '0',传 0 进去不会匹配字符串 '0'。
- 第二个参数不传 → 返回全部键名
- 传了但值不存在 → 返回空数组
[] - 传的是浮点数或布尔值,要小心隐式转换陷阱(比如
true不等于1,除非开启松散比较,但array_keys不支持)
要找“所有重复值对应的键”,得先分组再遍历
单靠 array_keys 无法自动发现哪些值重复、哪些只出现一次。它没有聚类能力。你得先用 array_count_values 统计频次,再挑出数量 >1 的值,最后对每个这样的值调用 array_keys。
示例:
$data = ['a' => 'cat', 'b' => 'dog', 'c' => 'cat', 'd' => 'bird', 'e' => 'dog'];
$counts = array_count_values($data); // ['cat'=>2, 'dog'=>2, 'bird'=>1]
$duplicates = array_filter($counts, fn($n) => $n > 1); // ['cat'=>2, 'dog'=>2]
$result = [];
foreach (array_keys($duplicates) as $val) {
$result[$val] = array_keys($data, $val);
}
// $result = ['cat' => ['a', 'c'], 'dog' => ['b', 'd']]
- 别直接在
array_count_values结果上用array_keys—— 那返回的是值的名称(如'cat'),不是原数组的键 - 如果原数组键是数字且不连续,
array_keys($data, $val)返回的就是原始键,不会重排 - 大数组时注意性能:两次遍历(统计 + 查键)是必要开销,没更省事的办法
遇到关联数组和 null / false 值要特别小心
array_keys($arr, null) 会匹配 null,但也会匹配未定义的键(如果用 isset 判断过就知道这不是一回事)。更麻烦的是 false:它会匹配 false、0、''、null 吗?不会——因为 array_keys 用的是严格比较,但你传参时如果写成 array_keys($arr, false),它只认 false,其他三个都不算。
- 想同时抓
false和0?不能依赖array_keys,得自己循环 + 松散判断 - 键名含对象或资源?不行。
array_keys要求输入是数组,且值可比较;对象不能用===安全比(除非是同一引用) - 值是浮点数?避免用
array_keys($arr, 0.1 + 0.2),浮点误差会让匹配失败,先round()或转字符串再比
替代方案:用 foreach 手动收集更可控
当逻辑变复杂(比如要排除某些键、要合并多条件、要保留键值对结构),硬套 array_keys 反而绕弯。直接 foreach 遍历一次,边走边存,代码反而短、意图更清、调试也方便。
例如,只要键名是字符串且值重复超过一次的键:
$lookup = [];
$repeatedKeys = [];
foreach ($data as $key => $val) {
if (!is_string($key)) continue;
$hash = is_object($val) ? spl_object_hash($val) : serialize($val);
if (!isset($lookup[$hash])) {
$lookup[$hash] = [$key];
} else {
$lookup[$hash][] = $key;
if (count($lookup[$hash]) === 2) { // 第二次见,才加入结果
$repeatedKeys[$val] = $lookup[$hash];
}
}
}
- 用
serialize处理任意类型值(包括数组),比===更通用 - 提前判断键类型、跳过不需要的项,
array_keys做不到这点 - 内存占用略高,但对几千条数据完全无感;真到百万级,再考虑生成器或数据库层解决
实际用的时候,多数情况第一种“array_count_values + 循环 array_keys”够用;但只要需求里带“排除”“条件过滤”“类型混合”,就别硬撑,直接上 foreach。函数组合看着高级,可读性和维护性常不如几行直白的循环。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











