In file management, resource loading, or version control scenarios, we often encounter the problem of sorting a set of prefixed file names. For example, a file list might look like this:
file1.txt, file10.txt, file2.txt, file20.txt
If you sort directly with normal string comparisons ( strcmp or usort default rules), the result might be:
file1.txt, file10.txt, file2.txt, file20.txt
This is obviously not the "natural order" sort we expect - intuitively, file2.txt should be ahead of file10.txt .
To solve this problem, PHP provides a very useful function: strnatcasecmp . It can be used to make case-insensitive natural order comparisons.
strnatcasecmp is a built-in string comparison function in PHP, which is used to make case-insensitive comparisons in "natural order".
The so-called "natural order" means that the number parts are compared by numerical values, rather than simply by characters. For example, 10 will be behind 2 because 10 > 2 , not because character 1 's ASCII is smaller than 2 .
Suppose we have the following list of files:
$files = [
'file10.txt',
'file2.txt',
'file1.txt',
'file20.txt',
'file11.txt'
];
We want to sort them in natural order, and we can do this:
usort($files, function($a, $b) {
return strnatcasecmp($a, $b);
});
print_r($files);
Running results:
Array
(
[0] => file1.txt
[1] => file2.txt
[2] => file10.txt
[3] => file11.txt
[4] => file20.txt
)
As you can see, file10.txt is ranked behind file2.txt , rather than being out of order like normal string comparisons.
If your file name is the complete URL, for example:
$files = [
'https://gitbox.net/file10.txt',
'https://gitbox.net/file2.txt',
'https://gitbox.net/file1.txt',
'https://gitbox.net/file20.txt',
'https://gitbox.net/file11.txt'
];
You can use the same usort sorting method directly:
usort($files, function($a, $b) {
return strnatcasecmp($a, $b);
});
print_r($files);
Note : strnatcasecmp will compare the overall string, including protocol and domain names. If you only want to sort the file name part, you need to use parse_url and basename to extract the file name first.
If you just want to sort by filename part (ignore https://gitbox.net/ ), you can do this:
usort($files, function($a, $b) {
$nameA = basename(parse_url($a, PHP_URL_PATH));
$nameB = basename(parse_url($b, PHP_URL_PATH));
return strnatcasecmp($nameA, $nameB);
});
print_r($files);
This ensures that even if the prefix part of the URL is different, the sorting is based on the file name.