在日常 PHP 编程中,我们经常需要对字符串数组进行排序,但默认的字典序排序(sort、usort 等)并不能很好地处理带有数字的字符串。比如 img1.png, img2.png, img10.png 这样的文件名,如果用普通的字符串比较,排序结果会是 img1.png, img10.png, img2.png,显然不符合人类的自然排序习惯。
为了实现“自然排序”,PHP 提供了 strnatcmp 和 strnatcasecmp 函数,分别对应区分大小写和不区分大小写的自然排序。
另外,当我们对数组排序时,常常还需要对数组中的每个元素统一格式化,比如全部转小写或去掉多余空格,这时候可以用 array_map 来实现。
本文将介绍如何将这两个工具结合起来,对数组中的字符串进行统一格式化后,再进行自然排序。
1?? 准备数据数组
我们以一组文件名为例:
$files = ['Img10.png', 'img2.png', 'IMG1.png', 'img20.png', 'img11.png'];
2?? 使用 array_map 格式化元素
假设我们想把它们全部转为小写:
$formattedFiles = array_map('strtolower', $files);
如果要更复杂的处理(比如去空格、统一扩展名),可以写成匿名函数:
$formattedFiles = array_map(function($item) {
return strtolower(trim($item));
}, $files);
3?? 自定义排序函数
PHP 的 usort 允许我们用自定义函数排序:
usort($formattedFiles, 'strnatcasecmp');
注意:strnatcasecmp 是一个比较函数,而不是直接用于排序的函数。
<?php
$files = ['Img10.png', 'img2.png', 'IMG1.png', 'img20.png', 'img11.png'];
// 第一步:统一格式(转小写 + 去空格)
$formattedFiles = array_map(function($item) {
return strtolower(trim($item));
}, $files);
// 第二步:自然排序(不区分大小写)
usort($formattedFiles, 'strnatcasecmp');
// 输出结果
foreach ($formattedFiles as $file) {
echo $file . "\n";
}
?>
运行结果:
img1.png
img2.png
img10.png
img11.png
img20.png
假设我们处理的是一组 URL:
$urls = [
'https://gitbox.net/File10.html',
'https://gitbox.net/file2.html',
'https://gitbox.net/FILE1.html',
'https://gitbox.net/file20.html',
'https://gitbox.net/file11.html',
];
我们想按文件名部分排序,可以先提取文件名,再排序:
<?php
$urls = [
'https://gitbox.net/File10.html',
'https://gitbox.net/file2.html',
'https://gitbox.net/FILE1.html',
'https://gitbox.net/file20.html',
'https://gitbox.net/file11.html',
];
// 提取文件名部分并绑定到 URL
$mapped = array_map(function($url) {
$parts = parse_url($url);
$file = basename($parts['path']);
return ['url' => $url, 'file' => strtolower($file)];
}, $urls);
// 按文件名自然排序
usort($mapped, function($a, $b) {
return strnatcasecmp($a['file'], $b['file']);
});
// 输出排序后的 URL
foreach ($mapped as $item) {
echo $item['url'] . "\n";
}
?>
输出:
https://gitbox.net/FILE1.html
https://gitbox.net/file2.html
https://gitbox.net/File10.html
https://gitbox.net/file11.html
https://gitbox.net/file20.html