← PHP sizeof()函数教程:数组元素计数、count()别名关系与递归统计实战 array_splice()函数:PHP数组切片与替换的进阶用法 →

PHP sort()函数教程:数组升序排列、排序标志位与关联数组键名丢失实战

著
原创 2026-10-09 PHP 已有人查阅

一、函数定位与基本概念

sort()是PHP内置的数组排序函数,作用是把数组元素按升序重新排列。这个函数从PHP4.0开始提供,是数组排序操作中最基础的一个。

函数原型如下:

bool sort ( array &$array [, int $sort_flags = SORT_REGULAR ] );

参数说明:

参数 说明 是否必需
array 指定要排序的数组,以引用方式传入 必需
sort_flags 排序行为标志位,默认SORT_REGULAR 可选

返回值方面,sort()成功时返回true,失败时返回false。它返回的是布尔值,不是排序后的数组。数组本身通过引用被直接修改,调用后原数组的顺序已经变化。

排序标志位的可选值:

标志位 含义
SORT_REGULAR 按常规方式比较元素,默认值
SORT_NUMERIC 按数值方式比较元素
SORT_STRING 按字符串方式比较元素
SORT_LOCALE_STRING 按当前区域设置比较字符串
SORT_NATURAL 按自然顺序比较字符串
SORT_FLAG_CASE 可与SORT_STRING或SORT_NATURAL组合,忽略大小写

这里有一个关键机制需要先明确:sort()会为数组元素分配新的键。无论传入的是索引数组还是关联数组,排序之后所有键名都会被重建为从0开始的数字键。关联数组的字符串键会全部丢失,值和键的对应关系被切断。这个特性是sort()和asort()的核心区别,也是实际项目中最容易踩坑的地方。

二、基础用法与代码号学习编程示例

先看一个字符串数组的排序例子。代码号学习编程时,常用乐器名称数组来演示升序排列:

<?php
$guitars = array("classical", "acoustic", "electric");
sort($guitars);
print_r($guitars);
?>

输出结果为:

Array
(
    [0] => acoustic
    [1] => classical
    [2] => electric
)

sort()按字母顺序把三个元素重新排列。默认的SORT_REGULAR标志位对字符串来说,比较逻辑接近字典序。

再看一个汽车品牌数组:

<?php
$cars = array("bmw", "audi", "nissan");
sort($cars);
print_r($cars);
?>

输出结果为:

Array
(
    [0] => audi
    [1] => bmw
    [2] => nissan
)

audi排在bmw前面,nissan排在之后,符合字母升序。

再看一个课程名称数组:

<?php
$subject = array("os", "compiler", "dbms", "networking");
sort($subject);
print_r($subject);
?>

输出结果为:

Array
(
    [0] => compiler
    [1] => dbms
    [2] => networking
    [3] => os
)

这三个例子说明,sort()对字符串数组的排序结果符合字母表顺序。注意os排在之后,因为o的字母序在n之后。

三、数值排序与rsort()对比

第三个例子展示了rsort()和sort()的配合使用,也暴露了数值排序中需要注意的地方:

<?php
$numbers = array(50, 100, 20, 1, 400);
rsort($numbers);
print_r($numbers);
sort($numbers);
print_r($numbers);
?>

输出结果为:

Array
(
    [0] => 400
    [1] => 100
    [2] => 50
    [3] => 20
    [4] => 1
)
Array
(
    [0] => 1
    [1] => 20
    [2] => 50
    [3] => 100
    [4] => 400
)

rsort()是sort()的降序版本,把数组从大到小排列。sort()再把它从小到大排列。两次操作都直接修改了原数组。

这里有一个项目实战中的踩坑经历。曾经处理价格数据时,价格从数据库取出时是字符串类型,比如"100"、"50"、"20"。直接调用sort()后,结果变成了"100"、"20"、"50",因为默认的SORT_REGULAR在比较字符串数字时,按字符串规则处理,"100"的首字符1小于"20"的首字符2,所以"100"排在了前面。

解决方法是显式指定SORT_NUMERIC:

<?php
$prices = array("100", "50", "20");
sort($prices, SORT_NUMERIC);
print_r($prices);
?>

输出结果为:

Array
(
    [0] => 20
    [1] => 50
    [2] => 100
)

这个经历说明,当数组中元素的类型不确定,或者元素是字符串形式的数字时,指定SORT_NUMERIC可以避免按字符串规则排序带来的偏差。

四、排序标志位的选择策略

排序标志位决定了sort()内部如何比较元素。选错标志位会导致排序结果偏离预期。

SORT_REGULAR:默认值,按PHP的常规比较规则处理。对数字和字符串混合的数组,比较规则比较复杂。PHP8之前,字符串和数字比较时行为有过多次调整。如果数组类型统一,SORT_REGULAR通常够用。如果类型混杂,建议显式指定标志位。

SORT_NUMERIC:按数值比较。适合元素是数字或数字字符串的场景。价格、数量、评分、年龄等数据排序时使用。

SORT_STRING:按字符串比较。适合元素是文本的场景。注意字符串比较是逐字节进行的,大写字母和小写字母的排序位置不同。

SORT_LOCALE_STRING:按当前区域设置比较字符串。适合需要处理多语言排序的场景,比如中文拼音排序、欧洲语言的特殊字符排序。使用前需要确认服务器安装了对应的locale。

SORT_NATURAL:自然顺序排序。适合包含数字的字符串,比如"img1"、"img2"、"img10"。默认的SORT_STRING会把"img10"排在"img2"前面,因为逐字符比较时1小于2。SORT_NATURAL会按人类直觉把"img2"排在"img10"前面。

<?php
$files = array("img10", "img2", "img1");
sort($files, SORT_NATURAL);
print_r($files);
?>

输出结果为:

Array
(
    [0] => img1
    [1] => img2
    [2] => img10
)

SORT_FLAG_CASE:这个标志位不能单独使用,需要和SORT_STRING或SORT_NATURAL组合,实现忽略大小写的排序。

<?php
$words = array("Banana", "apple", "Cherry");
sort($words, SORT_STRING | SORT_FLAG_CASE);
print_r($words);
?>

输出结果为:

Array
(
    [0] => apple
    [1] => Banana
    [2] => Cherry
)

个人建议:在业务代码中,只要数组元素的类型是明确的,就显式指定排序标志位。这样代码意图更清楚,也不受PHP版本间比较规则变化的影响。

五、关联数组键名丢失问题

这是sort()最需要警惕的地方。看下面这个例子:

<?php
$score = array("张三" => 85, "李四" => 92, "王五" => 78);
sort($score);
print_r($score);
?>

输出结果类似:

Array
(
    [0] => 78
    [1] => 85
    [2] => 92
)

原本的键名"张三"、"李四"、"王五"全部消失,变成了0、1、2。值和姓名的对应关系被彻底切断。排序后的数组只知道分数,不知道谁得了多少分。

项目实战中有一次做成绩排名功能,学生姓名和分数用关联数组存储,键名是姓名,值是分数。为了按分数排序,直接对数组调用了sort()。结果分数排序了,但姓名丢失了,排名结果无法对应到学生。后来改用asort()才解决了问题。

asort()按值排序但保留键名,适合关联数组:

<?php
$score = array("张三" => 85, "李四" => 92, "王五" => 78);
asort($score);
print_r($score);
?>

输出结果为:

Array
(
    [王五] => 78
    [张三] => 85
    [李四] => 92
)

键名和值的对应关系保持完好,分数按升序排列,姓名跟随分数一起移动。

这个踩坑经历说明:如果数组的键名承载业务含义,比如姓名、ID、标识符,直接使用sort()会破坏这种关系。正确的做法是根据需求选择asort()(按值排序保留键名)、ksort()(按键名排序)或arsort()(按值降序保留键名)。

六、sort()家族与相关函数对比

sort()和几个函数容易混淆,需要分清使用场景。

sort()与rsort():sort()升序,rsort()降序。两者都重建键名,都修改原数组。

sort()与asort():sort()按值升序但重建键名,asort()按值升序但保留键名。关联数组排序用asort()。

sort()与ksort():sort()按值排序,ksort()按键名排序。需要按键名顺序整理数组时用ksort()。

sort()与usort():sort()使用内置比较规则,usort()使用用户自定义比较函数。需要按复杂规则排序时用usort()。

sort()与array_multisort():sort()对单个数组排序,array_multisort()可以对多个数组同时排序,或者对多维数组按指定列排序。处理表格数据、多列排序时用array_multisort()。

个人见解:sort()的定位是“对值排序,不关心键名”的场景。如果键名重要,就应该换用asort()或ksort()。选择排序函数时,先问两个问题:按值还是按键?键名要不要保留?这两个问题的答案就能确定用哪个函数。

七、本节课程知识要点

  • sort()用于对数组元素按升序排列,原数组以引用方式被直接修改。

  • 函数返回布尔值,成功为true,失败为false,不返回排序后的数组。

  • 无论传入索引数组还是关联数组,排序后键名都会重建为从0开始的数字键。

  • 关联数组的字符串键在sort()后会丢失,键值对应关系被切断。

  • 键名有业务含义时,应使用asort()按值排序保留键名,或ksort()按键名排序。

  • SORT_REGULAR是默认标志位,类型混杂时建议显式指定SORT_NUMERIC或SORT_STRING。

  • SORT_NATURAL适合包含数字的字符串,SORT_FLAG_CASE需要与其他标志位组合使用。

  • 字符串形式的数字排序时,不指定SORT_NUMERIC会按字符串规则处理,结果可能偏离预期。

  • 需要按键名排序用ksort(),需要自定义规则用usort(),需要多数组联动排序用array_multisort()。

sort()的用法本身不复杂,核心在于理解它的引用修改和键名重建两个特性,以及排序标志位对比较规则的影响。把这两个点弄清楚,再根据业务需求选择保留键名还是重建键名,数组排序就不会出问题。

← PHP sizeof()函数教程:数组元素计数、count()别名关系与递归统计实战 array_splice()函数:PHP数组切片与替换的进阶用法 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号