用usort()配合strlen()或mb_strlen()可实现按字符串长度排序:索引数组用usort,关联数组用uasort;UTF-8需用mb_strlen()并指定编码;大数据量时宜采用预计算长度的Schwartzian变换优化性能。

用 usort() 配合 strlen() 实现按值长度排序
PHP 没有内置的“按字符串长度排序”函数,最直接可靠的方式是用 usort() 自定义比较逻辑。它原地修改数组,不改变键名(数值索引会重排,关联键保留),适合大多数场景。
常见错误是误用 sort() 或 asort() ——它们只按值大小或字典序排,和长度无关。
- 对索引数组:
usort($arr, fn($a, $b) => strlen($a) strlen($b)); - 对关联数组需保持键值关系:用
uasort($arr, fn($a, $b) => strlen($a) strlen($b)); - 升序排(短→长)用
;降序(长→短)就写成strlen($b) strlen($a) - 注意
strlen()对null、数字、对象会返回 0 或触发警告,排序前建议过滤或转换为字符串:(string)$a
遇到中文或 UTF-8 多字节字符怎么办
strlen() 返回的是字节数,不是字符数。一个中文 UTF-8 字符占 3 字节,strlen('你好') 得到 6,但你通常想按“2 个字符”排序。
这时候必须换用 mb_strlen(),并指定编码:
立即学习“PHP免费学习笔记(深入)”;
- 确保已启用
mbstring扩展(绝大多数现代 PHP 环境默认开启) - 替换比较函数:
fn($a, $b) => mb_strlen($a, 'UTF-8') mb_strlen($b, 'UTF-8') - 如果数据编码不确定,统一转成 UTF-8 再算:
mb_strlen(mb_convert_encoding($a, 'UTF-8', 'auto'), 'UTF-8')
性能敏感时别在回调里重复计算
如果数组很大(比如上万项),每次比较都调用两次 strlen() 或 mb_strlen() 会带来明显开销。
更高效的做法是预计算长度,用“装饰-排序-剥离”模式(Schwartzian transform):
$decorated = array_map(fn($v) => ['len' => mb_strlen($v, 'UTF-8'), 'val' => $v], $arr); usort($decorated, fn($a, $b) => $a['len'] <=> $b['len']); $result = array_column($decorated, 'val');
虽然多一次遍历,但避免了 O(n log n) 次函数调用,实测在 >5000 元素时差异明显。
为什么不用 array_multisort()
有人试过先用 array_map('strlen', $arr) 提取长度数组,再用 array_multisort($lengths, $arr)。这看似简洁,但有几个硬伤:
- 对关联数组无效 ——
array_multisort()会重置键名,丢失原始键映射 - 无法处理 UTF-8 字符,除非手动套
mb_strlen并确保长度数组与原数组严格对齐 - 空值或非字符串类型会导致
strlen()返回 false 或 0,引发错位 - 可读性和维护性不如
usort+ 匿名函数直观
真正需要同时按多个字段排序(比如先按长度、再按字典序)时,usort 依然更可控。



















