在文件管理、資源加載或版本控制場景中,我們經常會遇到需要對一組帶有前綴的文件名進行排序的問題。例如,文件列表可能是這樣的:
file1.txt, file10.txt, file2.txt, file20.txt
如果直接用普通的字符串比較( strcmp或usort默認規則)排序,結果可能是:
file1.txt, file10.txt, file2.txt, file20.txt
這顯然不是我們期望的「自然順序」排序—— 直觀上, file2.txt應該排在file10.txt前面。
為了解決這個問題,PHP 提供了一個非常好用的函數: strnatcasecmp 。它可以用來進行不區分大小寫的自然順序比較。
strnatcasecmp是PHP 內置的字符串比較函數,作用是按照「自然順序」進行不區分大小寫的比較。
所謂「自然順序」是指:數字部分按數值比較,而不是單純按字符比較。例如, 10會排在2後面,因為10 > 2 ,而不是因為字符1的ASCII 比2小。
假設我們有以下文件列表:
$files = [
'file10.txt',
'file2.txt',
'file1.txt',
'file20.txt',
'file11.txt'
];
我們想按照自然順序排序它們,可以這樣做:
usort($files, function($a, $b) {
return strnatcasecmp($a, $b);
});
print_r($files);
運行結果:
Array
(
[0] => file1.txt
[1] => file2.txt
[2] => file10.txt
[3] => file11.txt
[4] => file20.txt
)
可以看到, file10.txt排在了file2.txt後面,而不是像普通字符串比較那樣亂序。
假如你的文件名是完整的URL,例如:
$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'
];
你可以直接用同樣的usort排序方式:
usort($files, function($a, $b) {
return strnatcasecmp($a, $b);
});
print_r($files);
注意: strnatcasecmp會從字符串的整體比較,包含協議和域名。如果你只想對文件名部分排序,需要先用parse_url和basename提取出文件名。
如果你只想按文件名部分(忽略https://gitbox.net/ )排序,可以這樣做:
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);
這樣就可以確保即使URL 的前綴部分不同,排序也是根據文件名來進行的。