array_flip 会丢弃重复的值,只保留最后一个键;它将原数组的值作为新键、原键作为新值,要求值必须为字符串或整数,重复值仅保留最后出现的对应键。

array_flip 会丢弃重复的值,只保留最后一个键
PHP 的 array_flip 不是简单地“一一对应交换”,它把原数组的值变成新数组的键,原键变成新值。但值必须能作为合法键(即字符串或整数),且**如果多个元素值相同,只有最后一个会被保留**。
常见错误现象:
输入 ['a' => 1, 'b' => 1, 'c' => 2],结果却是 [1 => 'b', 2 => 'c'],'a' 消失了——因为 1 重复,被后出现的 'b' 覆盖。
- 使用场景:适合做“反向映射”,比如状态码 → 状态名,前提是值唯一
- 若原数组含非标量值(如数组、对象),
array_flip会报Warning: array_flip(): Can only flip STRING and INTEGER values! - 空字符串
''和0在弱类型比较下可能意外冲突(例如['a' => 0, 'b' => '']会因类型转换导致覆盖)
想保留所有键?不能直接用 array_flip
如果原始数组存在重复值,又需要记录所有原始键,array_flip 无能为力。得手动构建:
$original = ['a' => 1, 'b' => 1, 'c' => 2];
$flipped = [];
foreach ($original as $key => $value) {
if (!isset($flipped[$value])) {
$flipped[$value] = [];
}
$flipped[$value][] = $key;
}
// 结果:[1 => ['a', 'b'], 2 => ['c']]
- 这种结构叫“反向索引表”,适合查“哪些键对应某值”
- 注意
$value仍需是可作为键的类型;否则要先strval($value)或serialize($value)处理 - 性能上,
array_flip是 C 实现、极快;手动循环在大数据量时略慢,但可控
和 array_keys + array_values 混用容易误解
有人以为 array_flip($arr) ≡ array_combine(array_values($arr), array_keys($arr)),其实不等价:
立即学习“PHP免费学习笔记(深入)”;
-
array_values会重置键为数字索引,丢失原始键类型(比如原键是字符串'01',array_values后变成0) -
array_combine要求两个数组长度一致,且第二个参数(新键)不能有重复或非法值,否则直接失败并报 Warning -
array_flip内部处理更严格:自动跳过非法值,不中断执行
所以别为了“看起来更直观”去拆解它——徒增 bug 风险。
实际用例:快速判断值是否存在且获取原键
这是 array_flip 最实用的场景。比如配置项白名单:
$allowed_actions = ['create', 'read', 'update', 'delete'];
$flip_map = array_flip($allowed_actions); // ['create'=>0, 'read'=>1, ...]
if (isset($flip_map[$input_action])) {
// 安全,$input_action 确实在白名单中
$original_key = $flip_map[$input_action]; // 还能拿到原始索引位置
}
- 比
in_array($input_action, $allowed_actions, true)快,尤其数组大时(哈希查找 O(1) vs 线性扫描 O(n)) - 必须用
isset(),不能用array_key_exists()—— 因为array_flip可能产生null值键(如原数组有null值),而isset对null键返回 false - 如果原数组键不是连续数字,
$original_key就是原始键名,不是序号
真正要注意的是:翻转前确认值唯一、可作键、不含 null/数组/对象——这些条件漏掉一个,运行时就出问题。



















