sort() 会重置键名为连续数字索引,这是设计行为而非 bug;需保留键名时应根据排序需求选用 asort()、arsort()、ksort() 或 krsort()。

sort() 会重置键名,这是设计行为,不是 bug
sort() 的核心目标是对索引数组的**值**升序排列,并强制将结果转为连续数字键(0, 1, 2…)。它不关心原始键名,也不尝试保留它们。PHP 文档明确写:“此函数为 array 中的元素赋与新的键名。这将删除原有的键名,而不是仅仅将键名重新排序”。所以如果你传入 ['a' => 10, 'b' => 5],sort() 后得到的是 [0 => 5, 1 => 10] —— 键名 'a' 和 'b' 消失是预期结果。
该用哪个函数才能保留键名?
取决于你要按什么排序:
- 按**值**排序且需保留键名 → 用
asort()(升序)或arsort()(降序) - 按**键名**排序且需保留键名 → 用
ksort()(升序)或krsort()(降序) - 对二维数组按某个字段排序 → 用
array_multisort()+array_column(),它不改变原数组结构,自然保留键名
别用 sort() 处理关联数组 —— 它根本不是为这种场景设计的。
混合类型排序时,键名丢失只是表象,类型隐式转换才是真坑
当你传入 [10, '2', 25, '100'] 给 sort(),它默认用 SORT_REGULAR 比较:字符串 '2' 和整数 10 会被转成同一类型再比,结果是字典序优先,'2' 排在 10 前面。此时你看到的“顺序错乱”,和键名丢失一样,都是因函数选错导致的连锁反应。
立即学习“PHP免费学习笔记(深入)”;
正确做法是显式指定标志:
-
sort($arr, SORT_NUMERIC)强制数值比较 -
sort($arr, SORT_STRING)强制字符串比较 - 但注意:即使加了
SORT_NUMERIC,sort()依然会丢键名 —— 标志只管怎么比,不管怎么编号
array_unique 之后键名也“不见”了?那其实是另一回事
array_unique() 本身**不会重排键名** —— 它只删重复值,保留首次出现项的原始键。但很多人误以为键名丢了,是因为后续直接 foreach 或 json_encode 时发现键不连续,或想用 for ($i=0; $i<count> 遍历失败。这本质是索引断裂,不是函数删了键。</count>
若你确实需要连续数字键,得手动补上:
-
$clean = array_values(array_unique($arr))→ 重索引 -
$keepKeys = array_unique($arr, SORT_STRING)→ 仅去重,不动键
别把 array_unique 和 sort 的行为混为一谈:一个管去重,一个管排序,但都可能让你“找不到原来的键”,原因却完全不同。



















