Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】levenshtein()関数の使い方

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

作成日: 更新日:

基本的な使い方

levenshtein関数は、2つの文字列間の類似度を数値で示す「レーベンシュタイン距離」を計算する関数です。レーベンシュタイン距離とは、ある文字列を別の文字列に変換するために必要な、単一文字の挿入、削除、または置換といった操作の最小回数を指します。この距離の値が小さいほど、比較対象の2つの文字列はより似ていると判断できます。

この関数は、主にスペルチェック機能の実装や、入力されたキーワードの曖昧なマッチングを行う際などに非常に役立ちます。例えば、ユーザーが「aple」と入力した場合に、最も近い「apple」を提案するといった用途に利用できます。

levenshtein関数は、まず比較したい最初の文字列と二番目の文字列を必須の引数として受け取ります。さらに、オプションとして、文字の挿入、置換、削除にかかるコストをそれぞれ個別の整数値で指定することも可能です。これにより、特定の操作に対して異なる重み付けを行い、より柔軟な類似度計算を行うことができます。

関数は計算されたレーベンシュタイン距離を整数値で返します。文字列の長さが255文字を超える場合や、その他の無効な引数が与えられた場合には、エラーを示す-1が返される点に注意が必要です。PHP 8環境において、文字列の類似度を効率的に評価するための強力なツールとして活用できます。

構文(syntax)

1<?php
2$string1 = "kitten";
3$string2 = "sitting";
4$distance = levenshtein($string1, $string2);
5?>

引数(parameters)

string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1

  • string $string1: 比較対象となる最初の文字列
  • string $string2: 比較対象となる2番目の文字列
  • int $insertion_cost = 1: 文字列1から文字列2へ挿入する際のコスト(デフォルトは1)
  • int $replacement_cost = 1: 文字列1の文字を文字列2の文字へ置換する際のコスト(デフォルトは1)
  • int $deletion_cost = 1: 文字列1から文字を削除する際のコスト(デフォルトは1)

戻り値(return)

int

levenshtein関数の戻り値は、2つの文字列のレーベンシュタイン距離を表す整数です。レーベンシュタイン距離とは、一方の文字列をもう一方の文字列に変換するために必要な、挿入、削除、置換の最小回数を示します。

サンプルコード

PHP levenshtein関数で文字列距離を計算する

1<?php
2
3/**
4 * levenshtein関数の使用例を示すスクリプト。
5 * この関数は、2つの文字列間のレーベンシュタイン距離(編集距離)を計算します。
6 * レーベンシュタイン距離とは、一方の文字列をもう一方に変換するために必要な、
7 * 最小限の単一文字編集(挿入、削除、置換)操作の数を表します。
8 */
9
10// 比較する文字列を定義します。
11$string1 = "kitten";
12$string2 = "sitting";
13$string3 = "sittin";
14
15echo "--- 基本的なレーベンシュタイン距離の計算 (デフォルトコスト) ---" . PHP_EOL;
16
17// デフォルトのコスト(挿入、置換、削除がそれぞれ1)でレーベンシュタイン距離を計算します。
18// 'kitten' を 'sitting' にするには、'k'->'s', 'e'->'i', 'n'->'g' の3回の置換が必要です。
19$distanceDefault = levenshtein($string1, $string2);
20echo "文字列 '{$string1}' と '{$string2}' のレーベンシュタイン距離: {$distanceDefault}" . PHP_EOL;
21
22// 'kitten' を 'sittin' にするには、'k'->'s', 'e'->'i' の2回の置換が必要です。
23$distanceDefault2 = levenshtein($string1, $string3);
24echo "文字列 '{$string1}' と '{$string3}' のレーベンシュタイン距離: {$distanceDefault2}" . PHP_EOL;
25
26echo PHP_EOL . "--- カスタムコストでのレーベンシュタイン距離の計算 ---" . PHP_EOL;
27
28// カスタムコストを指定してレーベンシュタイン距離を計算します。
29// 例として、置換コストを高く設定し、置換操作の「重み」を増やしてみます。
30$insertionCost   = 1;  // 文字の挿入にかかるコスト
31$replacementCost = 10; // 文字の置換にかかるコスト
32$deletionCost    = 1;  // 文字の削除にかかるコスト
33
34$distanceCustom = levenshtein($string1, $string2, $insertionCost, $replacementCost, $deletionCost);
35echo "文字列 '{$string1}' と '{$string2}' のレーベンシュタイン距離 (カスタムコスト: 挿入={$insertionCost}, 置換={$replacementCost}, 削除={$deletionCost}): {$distanceCustom}" . PHP_EOL;
36
37echo PHP_EOL . "--- その他の例 ---" . PHP_EOL;
38
39// 同じ文字列の場合の距離は0になります。
40$strA = "php";
41$strB = "php";
42$distanceSame = levenshtein($strA, $strB);
43echo "文字列 '{$strA}' と '{$strB}' のレーベンシュタイン距離 (デフォルトコスト): {$distanceSame}" . PHP_EOL;
44
45// 挿入が必要な場合の例 ('php' から 'phps' へは 's' の挿入1回)
46$strC = "phps";
47$distanceInsert = levenshtein($strA, $strC);
48echo "文字列 '{$strA}' と '{$strC}' のレーベンシュタイン距離 (デフォルトコスト): {$distanceInsert}" . PHP_EOL;
49
50// 削除が必要な場合の例 ('phps' から 'php' へは 's' の削除1回)
51$distanceDelete = levenshtein($strC, $strA);
52echo "文字列 '{$strC}' と '{$strA}' のレーベンシュタイン距離 (デフォルトコスト): {$distanceDelete}" . PHP_EOL;

levenshtein関数は、PHP 8で利用できる文字列操作関数の一つで、二つの文字列間のレーベンシュタイン距離を計算します。レーベンシュタイン距離とは、一方の文字列をもう一方の文字列に変換するために必要な、最小限の単一文字編集操作(文字の挿入、削除、または置換)の数を指します。

この関数は、比較対象となるstring1string2の二つの文字列を引数として受け取ります。加えて、オプションでinsertion_cost(文字の挿入にかかるコスト)、replacement_cost(文字の置換にかかるコスト)、deletion_cost(文字の削除にかかるコスト)を整数値で指定できます。これらのコストを省略した場合、デフォルト値としてそれぞれ1が設定されます。関数の戻り値は、計算されたレーベンシュタイン距離を示す整数値です。

サンプルコードでは、「kitten」と「sitting」のように異なる文字列間の距離を計算し、一方をもう一方に変換するために必要な編集操作の回数を確認しています。デフォルトのコスト設定(すべての操作が1)では、3回の操作で「kitten」を「sitting」に変換できることが示されています。また、カスタムコストを設定する例では、例えば置換コストを高く設定することで、置換操作の「重み」を変えて距離の計算結果がどのように変化するかを把握できます。これにより、システムの要件に応じて特定の編集操作をより重要視した距離を算出することが可能です。同じ文字列同士の距離は0となり、文字の挿入や削除のみで変換できる場合の距離も明確に算出されます。

levenshtein関数は、2つの文字列間の「レーベンシュタイン距離(編集距離)」を計算し、一方をもう一方に変換するために必要な最小限の編集操作(挿入、削除、置換)の回数を整数で返します。この距離が小さいほど、文字列は類似していると判断できます。引数では、比較する2つの文字列に加えて、挿入、置換、削除の各操作にかかるコストを数値で指定できます。デフォルトはすべて1ですが、コストを調整することで特定の操作の重みを変更することが可能です。この関数は文字列の大文字・小文字を区別して処理しますので、必要に応じてstrtolowerなどの関数で事前に揃えることを検討してください。非常に長い文字列を比較する場合、計算に時間がかかる可能性があるため、パフォーマンスには注意が必要です。

PHPで文字列類似度パーセンテージを計算する

1<?php
2
3/**
4 * 2つの文字列間のレーベンシュタイン距離に基づいた類似度パーセンテージを計算します。
5 *
6 * レーベンシュタイン距離は、ある文字列を別の文字列に変換するのに必要な
7 * 単一文字(バイト)の挿入、削除、置換の最小回数を数えます。
8 * この関数は、その距離を利用して文字列の類似度をパーセンテージで表現します。
9 *
10 * 注意: PHPの {@see levenshtein()} 関数はマルチバイト文字をサポートしていません。
11 *      そのため、日本語などのマルチバイト文字列を比較すると、正確な結果が得られない場合があります。
12 *      この関数は、主にASCII文字(半角英数字など)の比較に適しています。
13 *
14 * @param string $string1 比較する最初の文字列。
15 * @param string $string2 比較する2番目の文字列。
16 * @param int $insertionCost 挿入操作のコスト。デフォルトは1。
17 * @param int $replacementCost 置換操作のコスト。デフォルトは1。
18 * @param int $deletionCost 削除操作のコスト。デフォルトは1。
19 * @return float 2つの文字列間の類似度パーセンテージ (0.0 から 100.0)。
20 *               どちらかの文字列が空の場合、または最大長が0の場合、0.0を返します。
21 */
22function calculateStringSimilarityPercentage(
23    string $string1,
24    string $string2,
25    int $insertionCost = 1,
26    int $replacementCost = 1,
27    int $deletionCost = 1
28): float {
29    // どちらかの文字列が空の場合、類似度は0%とみなします。
30    if ($string1 === '' || $string2 === '') {
31        return 0.0;
32    }
33
34    // levenshtein関数はバイト単位で動作するため、文字列の長さをバイト数で取得します。
35    $len1 = strlen($string1);
36    $len2 = strlen($string2);
37    $maxLength = max($len1, $len2);
38
39    // 最大長が0の場合(両方の文字列が空だった場合)、類似度は0%とみなします。
40    if ($maxLength === 0) {
41        return 0.0;
42    }
43
44    // レーベンシュタイン距離を計算します。
45    // これは、string1をstring2に変換するために必要な最小操作数です。
46    $levenshteinDistance = levenshtein($string1, $string2, $insertionCost, $replacementCost, $deletionCost);
47
48    // 類似度パーセンテージを計算します。
49    // (最大長 - 距離) / 最大長 * 100 の式で算出します。
50    // 結果が0.0から100.0の範囲に収まるように保証します。
51    $similarity = (($maxLength - $levenshteinDistance) / $maxLength) * 100;
52
53    return max(0.0, min(100.0, $similarity));
54}

このPHPコードは、2つの文字列がどれくらい似ているかをパーセンテージで計算するcalculateStringSimilarityPercentage関数を提供します。この関数の中心となるのはPHP標準のlevenshtein関数です。

levenshtein関数は、ある文字列を別の文字列に変換するために必要な、文字の挿入、削除、置換の最小回数(これをレーベンシュタイン距離と呼びます)を整数値で返します。比較したい2つの文字列を$string1$string2として渡します。また、各操作(挿入、置換、削除)にかかるコストを$insertionCost$replacementCost$deletionCostとしてそれぞれ設定でき、デフォルトは1です。これらのコストを変更することで、特定の操作により大きな重みを持たせることができます。

calculateStringSimilarityPercentage関数は、このレーベンシュタイン距離を利用して、文字列の類似度を0.0%から100.0%の浮動小数点数で返します。距離が短いほど、類似度パーセンテージは高くなります。ただし、PHPのlevenshtein関数はマルチバイト文字(日本語など)に対応していないため、このコードは主にASCII文字(半角英数字など)の比較に適しています。どちらかの文字列が空の場合、または文字列の最大長が0の場合は、類似度を0.0%と判断して返します。

このサンプルコードで利用されているPHPのlevenshtein関数は、文字列をバイト単位で比較します。そのため、日本語のようなマルチバイト文字を含む文字列を比較すると、正確な距離が計算されず、結果として類似度パーセンテージも期待通りの値にならないことがあります。主にASCII文字(半角英数字など)の比較に適している点に特に注意が必要です。また、strlen関数も文字列のバイト数を取得するため、マルチバイト文字を扱う際には実際の文字数と混同しないよう気をつけましょう。挿入、置換、削除の各操作コストはデフォルトで1ですが、用途に応じて調整することで比較の重み付けを変えられます。計算される類似度パーセンテージは常に0.0から100.0の範囲で返されるため、直感的に結果を理解しやすいでしょう。

PHPで文字列比較:Levenshtein vs similar_text

1<?php
2
3declare(strict_types=1);
4
5/**
6 * Demonstrates the usage of the levenshtein and similar_text functions in PHP.
7 *
8 * This function illustrates how both functions compare strings, highlighting
9 * their different approaches: Levenshtein calculates the "edit distance,"
10 * while similar_text calculates character similarity and percentage.
11 * This helps beginners understand which function to use for specific string
12 * comparison needs.
13 */
14function demonstrateStringComparison(): void
15{
16    // Define sample strings for comparison.
17    // string1 and string2 have a small, single-character difference.
18    // string1 and string3 have more significant differences.
19    $string1 = 'PHP Developer';
20    $string2 = 'PHP Devloper';  // 'e' in 'Developer' changed to 'l'
21    $string3 = 'PHP Development'; // Different ending characters
22
23    echo "--- String Comparison Demo ---\n\n";
24
25    // --- Levenshtein Distance ---
26    // The levenshtein function calculates the minimum number of single-character
27    // edits (insertions, deletions, or substitutions) required to change one
28    // string into the other. A lower number indicates greater similarity in terms of edits.
29    echo "--- Levenshtein Distance (Edit Distance) ---\n";
30    echo "Measures the minimum number of single-character edits required to transform one string into another.\n\n";
31
32    // Compare $string1 and $string2
33    $levenshteinDistance12 = levenshtein($string1, $string2);
34    echo "Strings: \"{$string1}\" vs \"{$string2}\"\n";
35    echo "Levenshtein Distance: {$levenshteinDistance12} (1 edit: 'e' -> 'l')\n\n";
36
37    // Compare $string1 and $string3
38    $levenshteinDistance13 = levenshtein($string1, $string3);
39    echo "Strings: \"{$string1}\" vs \"{$string3}\"\n";
40    echo "Levenshtein Distance: {$levenshteinDistance13} (multiple edits needed)\n\n";
41
42
43    // --- Similar Text ---
44    // The similar_text function calculates the similarity between two strings
45    // by counting the number of identical characters in the same position.
46    // It can also calculate the similarity as a percentage.
47    echo "--- Similar Text (Similarity Count & Percentage) ---\n";
48    echo "Measures similarity by counting identical characters and calculating a percentage.\n\n";
49
50    $percent = 0.0; // Variable to store the similarity percentage
51
52    // Compare $string1 and $string2
53    // The third argument ($percent) is passed by reference to store the calculated percentage.
54    $similarCharCount12 = similar_text($string1, $string2, $percent);
55    echo "Strings: \"{$string1}\" vs \"{$string2}\"\n";
56    echo "Similar Characters: {$similarCharCount12}\n";
57    echo "Similarity Percentage: " . round($percent, 2) . "%\n\n";
58
59    // Compare $string1 and $string3
60    $similarCharCount13 = similar_text($string1, $string3, $percent);
61    echo "Strings: \"{$string1}\" vs \"{$string3}\"\n";
62    echo "Similar Characters: {$similarCharCount13}\n";
63    echo "Similarity Percentage: " . round($percent, 2) . "%\n\n";
64
65    echo "--- End of Demo ---\n";
66}
67
68// Execute the demonstration function to see the output.
69demonstrateStringComparison();

このPHPサンプルコードは、文字列の類似性を比較するlevenshtein関数とsimilar_text関数の使い方を、システムエンジニアを目指す初心者の方にもわかりやすく解説しています。

まず、levenshtein関数は、二つの文字列間で「レーベンシュタイン距離」(編集距離)を計算します。これは、ある文字列を別の文字列に変換するために必要な、最小限の単一文字の挿入、置換、削除の回数を示す値です。比較したい二つの文字列を引数に指定し、オプションで挿入・置換・削除のコストも設定可能です。戻り値は編集距離を示す整数値で、値が小さいほど文字列は「編集」の観点から似ていると判断されます。

次に、similar_text関数は、二つの文字列間で一致する文字の数を計算し、その類似度をパーセンテージで求めることができます。比較したい二つの文字列を引数に指定し、オプションで第三引数に参照渡しで変数を渡すと、類似度パーセンテージも受け取れます。戻り値は一致する文字の総数を示す整数値です。この関数は、文字列がどれだけ「共通の文字」を保持しているかに着目します。

これら二つの関数は、どちらも文字列の類似性を評価しますが、アプローチが異なります。levenshteinは「修正の労力」を、similar_textは「共通部分の割合」を測るため、用途に応じて使い分けが必要です。このサンプルコードを実行することで、それぞれの関数が返す結果の違いを比較し、用途に応じた選択の参考とすることができます。

PHPのlevenshteinsimilar_textは、文字列の類似度を測る目的が異なります。levenshteinは文字列を一致させるために必要な最小編集回数を返し、値が小さいほど似ていると判断します。一方、similar_textは共通する文字数とその類似度をパーセンテージで返し、値が大きいほど似ていると判断します。用途に応じて適切な関数を選んでください。 最も重要な注意点は、これらの関数はマルチバイト文字(日本語など)に直接対応していないことです。日本語を含む文字列を扱う場合、期待通りの結果を得るためには、mb_internal_encoding()の設定や、マルチバイト対応のライブラリを利用するなど、文字エンコーディングを考慮した前処理が別途必要となる場合があります。また、similar_text関数は、第三引数にパーセンテージを受け取るための変数を渡すと、その変数に計算結果が格納される点も把握しておきましょう。

関連コンテンツ

関連プログラミング言語