【PHP実践|実務向け】PHPで実現する「もしかして」機能:levenshtein関数による文字列の類似度判定

1. 導入

ユーザーが検索窓や入力フォームでスペルミスをした際、「もしかして: ~」と修正候補を表示する機能は、UX向上において非常に有効です。PHPには文字列間の距離を計算する標準関数であるlevenshtein()が用意されており、これを利用することで比較的容易に類似文字列を特定できます。本記事では、この関数の仕組みと、実務で不可欠な日本語(マルチバイト)対応の実装方法を解説します。

2. 基礎知識

levenshtein()とは、2つの文字列間での「レーベンシュタイン距離」を計算する関数です。これは、一方の文字列をもう一方の文字列に変形するために必要な「挿入・削除・置換」の最小回数を指します。数値が小さいほど、文字列が似ていることを意味します。
ただし、標準のlevenshtein()はシングルバイト文字列を前提としており、日本語などのマルチバイト文字を正しく扱えません。実務環境で日本語を扱う場合は、文字単位で処理を行う独自のロジックが必要です。

3. 実装/解決策

実装の基本は、候補となる単語リストと入力値を比較し、距離が一定以下のものを抽出することです。
実務上の注意点として、単語リストが数千〜数万件に及ぶ場合、全件ループで距離計算を行うとサーバー負荷が急増します。以下の対策を推奨します。
・文字数による絞り込み:長さが極端に異なる単語は除外する。
・閾値による早期終了:距離が0(完全一致)または1の場合に処理を中断する。
・事前計算:検索頻度の高い単語については、あらかじめハッシュ化しておく。

4. サンプルプログラム

以下は、マルチバイト対応の独自関数を用いた「もしかして」機能のサンプルです。

  • 簡易的な類似文字列検索サンプル
  • /

    // 候補リスト
    $wordlist = [“アップル”, “オレンジ”, “グレープ”, “バナナ”, “ブルーベリー”];
    $input = “アッブル”; // ユーザーの入力ミス

    // 日本語対応のlevenshtein距離計算関数
    function mb_levenshtein($str1, $str2) {
    $s1 = mb_str_split($str1, ‘utf-8’);
    $s2 = mb_str_split($str2, ‘utf-8’);
    $n = count($s1);
    $m = count($s2);

    $d = [];
    for ($i = 0; $i <= $n; $i++) $d[$i][0] = $i; for ($j = 0; $j <= $m; $j++) $d[0][$j] = $j; for ($i = 1; $i <= $n; $i++) { for ($j = 1; $j <= $m; $j++) { $cost = ($s1[$i - 1] === $s2[$j - 1]) ? 0 : 1; $d[$i][$j] = min($d[$i - 1][$j] + 1, $d[$i][$j - 1] + 1, $d[$i - 1][$j - 1] + $cost); } } return $d[$n][$m]; } $results = []; foreach ($wordlist as $word) { $dist = mb_levenshtein($input, $word); // 距離が2以下なら候補として保存 if ($dist > 0 && $dist <= 2) { $results[$word] = $dist; } } // 距離が近い順にソート asort($results); if (!empty($results)) { echo "もしかして: " . key($results); } else { echo "該当する候補は見つかりませんでした。"; } ?>

    5. 応用・注意点

    ・パフォーマンスの最適化:単語リストが膨大な場合は、PHP側で力技で計算するのではなく、Elasticsearchなどの検索エンジンが備える「Fuzzy Query」機能を利用することを強く推奨します。
    ・閾値の設定:許容距離(サンプル内の「2」)を大きくしすぎると、全く関係のない単語が候補として表示されてしまいます。対象とする単語の特性に合わせて調整してください。
    ・エンコーディング:mb_str_splitを使用する際は、必ずUTF-8で統一されていることを確認してください。文字化けが発生すると、正常に距離が計算されません。

    タイトルとURLをコピーしました