当前位置: 首页> 最新文章列表> 排序时如何防止 natsort 函数改变数组的原始键值?

排序时如何防止 natsort 函数改变数组的原始键值?

gitbox 2025-08-30

在 PHP 中,natsort 函数是一种常用的排序方法,它按照“自然顺序”对数组中的元素进行排序。这种排序方式能够更符合人类的阅读习惯,比如数字“10”会排在“2”之前,而不是传统的按 ASCII 码顺序排序。但在使用 natsort 进行排序时,可能会遇到一个问题——它会重置数组的键值,使得原来的键值丢失。这可能会导致在后续操作中,难以根据原始的键值来访问数据。

本文将讨论如何避免 natsort 改变数组的原始键值,并介绍一些相关的技巧和替代方法。

natsort 及其影响

natsort 函数的功能是基于“自然顺序”对数组进行排序。所谓自然顺序排序,是指在排序时将数字按其大小排序,而不是按字符串的字典顺序进行排序。例如:

<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-string">'a10'</span></span><span>, </span><span><span class="hljs-string">'a2'</span></span><span>, </span><span><span class="hljs-string">'a1'</span></span><span>, </span><span><span class="hljs-string">'a20'</span></span><span>];
</span><span><span class="hljs-title function_ invoke__">natsort</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>

执行上述代码后,输出结果如下:

<span><span><span class="hljs-title function_ invoke__">Array</span></span><span>
(
    [</span><span><span class="hljs-number">2</span></span><span>] =&gt; a1
    [</span><span><span class="hljs-number">1</span></span><span>] =&gt; a2
    [</span><span><span class="hljs-number">0</span></span><span>] =&gt; a10
    [</span><span><span class="hljs-number">3</span></span><span>] =&gt; a20
)
</span></span>

你可以看到,natsort 确实按数字的大小对数组进行了排序,但它重置了数组的键值,使得原来与元素相关的键不再保留。

如何防止键值丢失

如果你希望在使用 natsort 时保留原始的键值,可以在排序前先保存原数组的键值,然后再对排序后的数组进行重建。这样可以确保排序过程不会影响到原始的键值。

方法 1:使用 array_valuesnatsort

可以通过将数组的值提取出来进行排序,而保持键值不变。这是通过 array_values 函数实现的。具体做法是先保留原始的键值,再进行排序:

<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-string">'a'</span></span><span> =&gt; </span><span><span class="hljs-string">'a10'</span></span><span>, </span><span><span class="hljs-string">'b'</span></span><span> =&gt; </span><span><span class="hljs-string">'a2'</span></span><span>, </span><span><span class="hljs-string">'c'</span></span><span> =&gt; </span><span><span class="hljs-string">'a1'</span></span><span>, </span><span><span class="hljs-string">'d'</span></span><span> =&gt; </span><span><span class="hljs-string">'a20'</span></span><span>];

</span><span><span class="hljs-comment">// 保存原始键值</span></span><span>
</span><span><span class="hljs-variable">$original_keys</span></span><span> = </span><span><span class="hljs-title function_ invoke__">array_keys</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);

</span><span><span class="hljs-comment">// 对值进行自然排序</span></span><span>
</span><span><span class="hljs-title function_ invoke__">natsort</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);

</span><span><span class="hljs-comment">// 恢复原始键值</span></span><span>
</span><span><span class="hljs-variable">$array</span></span><span> = </span><span><span class="hljs-title function_ invoke__">array_combine</span></span><span>(</span><span><span class="hljs-variable">$original_keys</span></span><span>, </span><span><span class="hljs-variable">$array</span></span><span>);

</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>

输出结果:

<span><span><span class="hljs-title function_ invoke__">Array</span></span><span>
(
    [a] =&gt; a1
    [b] =&gt; a2
    [c] =&gt; a10
    [d] =&gt; a20
)
</span></span>

在这种方法中,首先通过 array_keys 获取原始键值,然后使用 natsort 排序数组。排序完成后,使用 array_combine 恢复键值与排序后的值的对应关系。

方法 2:使用 uasort 自定义排序

另一种方法是使用 uasort 函数进行自定义排序。与 natsort 类似,uasort 可以对数组进行排序,但它不会更改键值。通过实现自定义的排序函数,你可以控制排序方式,同时保留原始的键值:

<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-string">'a'</span></span><span> =&gt; </span><span><span class="hljs-string">'a10'</span></span><span>, </span><span><span class="hljs-string">'b'</span></span><span> =&gt; </span><span><span class="hljs-string">'a2'</span></span><span>, </span><span><span class="hljs-string">'c'</span></span><span> =&gt; </span><span><span class="hljs-string">'a1'</span></span><span>, </span><span><span class="hljs-string">'d'</span></span><span> =&gt; </span><span><span class="hljs-string">'a20'</span></span><span>];

</span><span><span class="hljs-title function_ invoke__">uasort</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(</span><span><span class="hljs-variable">$a</span></span><span>, </span><span><span class="hljs-variable">$b</span></span><span>) {
    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-title function_ invoke__">strnatcmp</span></span><span>(</span><span><span class="hljs-variable">$a</span></span><span>, </span><span><span class="hljs-variable">$b</span></span><span>);
});

</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>

uasort 通过回调函数实现排序,回调函数内部使用了 strnatcmp 函数来模拟自然顺序的排序方式,且不改变数组的键值。

输出结果:

<span><span><span class="hljs-title function_ invoke__">Array</span></span><span>
(
    [c] =&gt; a1
    [b] =&gt; a2
    [a] =&gt; a10
    [d] =&gt; a20
)
</span></span>

总结

尽管 natsort 是一个很强大的排序函数,但它会重置数组的键值。如果需要在排序过程中保留键值,您可以采用以下两种方法之一:

  1. 先保存原始键值,在排序后再通过 array_combine 恢复键值。

  2. 使用 uasort 函数进行自定义排序,从而避免键值丢失。

通过这两种方法,您可以确保数组在自然排序后,仍能保持原始的键值不变,避免排序过程中的数据丢失。