ファイル管理、リソースの読み込み、またはバージョン制御シナリオでは、プレフィックスされたファイル名のセットを並べ替えるという問題に遭遇することがよくあります。たとえば、ファイルリストは次のようになる場合があります。
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に遅れます。
次のファイルのリストがあるとします。
$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を使用してファイル名を最初に抽出する必要があります。
Filenameパーツでソートしたい場合( 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のプレフィックス部分が異なる場合でも、ソートはファイル名に基づいています。