【PHP8.x】strnatcmp関数の使い方

strnatcmp関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

strnatcmp関数は、人間が直感的に理解しやすい「自然順」アルゴリズムを使用して、2つの文字列を比較する関数です。この関数は、通常の文字列比較(たとえば strcmp 関数)が文字コード順(辞書順)で比較するのに対し、数字の並びを数値として認識して比較します。

具体的には、「file1.txt」、「file10.txt」、「file2.txt」のような文字列を比較する際、通常の比較では「file1.txt」の次に「file10.txt」、その後に「file2.txt」が来ます。しかし、strnatcmp関数を使うと、数字部分を数値として扱うため、「file1.txt」、「file2.txt」、「file10.txt」という、人間が期待する自然な順序で比較結果が得られます。

この関数は、比較したい2つの文字列を引数として受け取ります。戻り値は整数で、最初の文字列が2番目の文字列よりも小さい場合は負の値を、両者が等しい場合は0を、最初の文字列が大きい場合は正の値を返します。ファイル名やバージョン番号など、数字を含む文字列を正しくソートしたり比較したりする際に非常に有用です。この関数は、大文字と小文字を区別して比較します。大文字と小文字を区別しない自然順比較を行いたい場合は、strnatcasecmp 関数を使用します。

構文(syntax)

1<?php
2// strnatcmp は、人間が読むような自然な順番で文字列を比較します。
3// 通常の文字列比較と異なり、数字の並びを数値として扱います。
4// 結果は、最初の文字列が2番目の文字列より小さい場合は負の数、等しい場合は0、大きい場合は正の数を返します。
5
6$string_a = "img10.png";
7$string_b = "img2.png";
8
9// 自然順比較では "img10" は "img2" より大きいと判断されます。
10$result = strnatcmp($string_a, $string_b);
11echo $result; // 出力例: 1 (正の値)
12?>

引数(parameters)

string $string1, string $string2

  • string $string1: 比較対象の1つ目の文字列
  • string $string2: 比較対象の2つ目の文字列

戻り値(return)

int

文字列を、人間が理解する自然な順序で比較し、その結果を整数で返します。比較結果は、文字列が等しい場合は 0、最初の文字列が 2 番目の文字列より小さい場合は -1、大きい場合は 1 となります。

サンプルコード

PHP strnatcmp で文字列を比較する

1<?php
2
3declare(strict_types=1);
4
5/**
6 * 2つの文字列の先頭から指定したバイト数分を比較するサンプル関数
7 *
8 * この関数は、PHPの組み込み関数 `strncmp` の使用例を示します。
9 * `strncmp` は、バイナリセーフで大文字と小文字を区別して文字列を比較します。
10 *
11 * @param string $string1 比較する最初の文字列
12 * @param string $string2 比較する2番目の文字列
13 * @param int $length    比較する最大バイト数
14 * @return void
15 */
16function compareStrings(string $string1, string $string2, int $length): void
17{
18    // strncmp: 文字列の先頭から指定されたバイト数だけを比較します。
19    // $string1 が $string2 より小さい場合、負の数を返します。
20    // $string1 が $string2 より大きい場合、正の数を返します。
21    // 等しい場合は 0 を返します。
22    $result = strncmp($string1, $string2, $length);
23
24    echo "--- [{$string1}] と [{$string2}] を {$length} バイト比較 ---" . PHP_EOL;
25
26    if ($result < 0) {
27        echo "結果: 最初の文字列が小さいです。" . PHP_EOL;
28    } elseif ($result > 0) {
29        echo "結果: 最初の文字列が大きいです。" . PHP_EOL;
30    } else {
31        echo "結果: 2つの文字列は等しいです。" . PHP_EOL;
32    }
33    echo PHP_EOL;
34}
35
36// ケース1: 最初の5バイトが一致する例
37compareStrings("Hello world!", "Hello earth!", 5);
38
39// ケース2: 比較範囲内で違いがある例 ('w' > 'e')
40compareStrings("Hello world!", "Hello earth!", 8);
41
42// ケース3: 大文字と小文字は区別される例 ('h' > 'H')
43compareStrings("hello php", "Hello PHP", 5);
44
45// ケース4: 完全に一致する例
46compareStrings("PHP is fun", "PHP is fun", 10);
47
48?>

PHPのstrncmp関数は、2つの文字列の先頭から指定されたバイト数だけを比較するために使用されます。この比較は、文字コードのバイト値に基いて行われるため、大文字と小文字は異なるものとして厳密に区別されます。

この関数は3つの引数を取ります。第1引数と第2引数には比較したい2つの文字列を渡し、第3引数には比較を行うバイト数を整数で指定します。

関数の戻り値は、比較結果を示す整数です。第1引数の文字列が第2引数の文字列より小さいと判断された場合は負の数、大きい場合は正の数を返します。指定したバイト数の範囲で2つの文字列が完全に等しい場合は0が返されます。

サンプルコードは、strncmp関数の結果をif文で判定し、2つの文字列の関係を分かりやすく表示する例です。比較するバイト数を変えたり、大文字と小文字が混在する文字列を与えたりすることで、strncmpがどのように動作するかを具体的に示しています。これにより、文字列の部分的な一致や、大文字小文字の違いによる比較結果の変化を学ぶことができます。

提供されたリファレンスの関数名はstrnatcmpですが、サンプルコードではstrncmpが使用されています。これらは異なる目的を持つ関数ですので、混同しないようご注意ください。サンプルコードのstrncmpは、文字列の先頭から指定した「バイト数」分をバイナリセーフで比較し、大文字と小文字を区別します。日本語のようなマルチバイト文字を扱う場合、指定するバイト数と文字数が一致しないことがあるため、意図しない比較結果にならないよう注意が必要です。もし「ファイル10」「ファイル2」のように数字を含む文字列を、人間が読むような自然な順序で比較したい場合は、リファレンスにあるstrnatcmpの使用を検討してください。戻り値の負の値は最初の文字列が小さいこと、正の値は大きいこと、0は等しいことを示します。

PHP strnatcmpで自然順ソートする

1<?php
2
3declare(strict_types=1);
4
5/**
6 * strnatcmp() を使用して、ファイル名などを自然な順序でソートする例。
7 *
8 * この関数は、通常の文字列比較 (strcmp) と自然順比較 (strnatcmp) の違いを示します。
9 */
10function demonstrateNaturalOrderSort(): void
11{
12    // 比較対象のファイル名リスト
13    $files = ['img12.png', 'img10.png', 'img2.png', 'img1.png'];
14
15    echo '■ 元の配列:' . PHP_EOL;
16    print_r($files);
17    echo PHP_EOL;
18
19    // --- パターン1: 通常の文字列比較 (strcmp) ---
20    $sortedWithStrcmp = $files;
21    // usort()は、ユーザー定義の比較ロジックで配列をソートします。
22    // 'strcmp' を使うと、辞書順(文字コード順)で比較されます。
23    usort($sortedWithStrcmp, 'strcmp');
24
25    echo '■ strcmp() によるソート結果 (辞書順):' . PHP_EOL;
26    print_r($sortedWithStrcmp);
27    echo '// "img1" の次に "img10" が来てしまい、直感的な順序になりません。' . PHP_EOL;
28    echo PHP_EOL;
29
30
31    // --- パターン2: 自然順アルゴリズム (strnatcmp) ---
32    $sortedWithStrnatcmp = $files;
33    // 比較関数に 'strnatcmp' を指定します。
34    // この関数は文字列中の数字部分を数値として扱って比較します。
35    // 戻り値: $string1 < $string2 なら < 0, $string1 > $string2 なら > 0, 等しければ 0
36    usort($sortedWithStrnatcmp, 'strnatcmp');
37
38    echo '■ strnatcmp() によるソート結果 (自然順):' . PHP_EOL;
39    print_r($sortedWithStrnatcmp);
40    echo '// 数字が数値として (2 < 10 < 12) 評価され、人間が期待する順序でソートされます。' . PHP_EOL;
41}
42
43// 関数を実行して結果を表示
44demonstrateNaturalOrderSort();
45
46?>

PHPのstrnatcmp関数は、2つの文字列を「自然順アルゴリズム」で比較します。これは、文字列に含まれる数字部分を数値として解釈し、人間が直感的に並べ替えるのと同じような順序で比較を行うための関数です。

この関数は、比較対象となる2つの文字列 $string1$string2 を引数に取ります。戻り値は整数で、$string1$string2 より小さい場合は負の値、大きい場合は正の値、両者が等しい場合は0を返します。この仕様は、usort関数などを用いて配列をソートする際の比較ロジックとして利用するのに適しています。

サンプルコードでは、ファイル名の配列をソートする例を通して、通常の文字列比較 strcmpstrnatcmp の違いを示しています。strcmp を使うと文字コード順に比較されるため、「img1.png」の次に「img10.png」が来てしまいます。一方、strnatcmp を使うと、数字の「2」と「10」が数値として比較されるため、「img2.png」が「img10.png」より前になり、「img1.png」「img2.png」「img10.png」「img12.png」という期待通りの順序に並べ替えられます。このように、バージョン番号やファイル名など、数字を含む要素を自然な順序で扱いたい場合に非常に便利な関数です。

strnatcmp関数は、数字を含む文字列を人間が理解しやすい自然な順序で比較する際に使用します。strcmpのような通常の比較では、「10」が「2」より先にソートされることがありますが、strnatcmpでは数字部分を数値として評価するため、この問題を解決できます。ファイル名リストなどをソートする際に特に有用です。この関数は大文字と小文字を区別して比較しますので、大文字小文字を区別しない自然順比較を行いたい場合は、strnatcasecmp関数を利用してください。比較結果は、最初の文字列が小さい場合は負の数、大きい場合は正の数、等しい場合はゼロが返されます。

関連コンテンツ

【PHP8.x】strnatcmp関数の使い方 | いっしー@Webエンジニア