PHP で Soundex を使って類似発音の単語をグループ化する
PHP には、soundex()
という組み込み関数が用意されており、このアルゴリズムを実装しています。この関数は、文字列を渡すと、その文字列の Soundex コードを返します。Soundex コードは、4 文字の英数字列で、先頭の文字と、その後に続く 3 つの音節を表します。
Soundex コードの計算方法
Soundex コードを計算するには、次の手順に従います。
- 文字列の先頭文字を大文字に変換します。
- 以下の表に従って、文字列の残りの部分をエンコードします。
文字 | エンコード |
---|---|
A | A |
B | B |
C | C |
D | D |
E | E |
F | F |
G | G |
H | H |
I | |
J | J |
K | K |
L | L |
M | M |
N | N |
O | O |
P | P |
Q | Q |
R | R |
S | S |
T | T |
U | U |
V | V |
W | W |
X | X |
Y | Y |
Z | Z |
- 同じ音節コードが連続する場合は、最初のコードのみを残します。
- コードが 4 文字に達するまで、2 と 3 の手順を繰り返します。
- コードの長さが 4 文字未満の場合は、末尾に 0 を追加します。
例
以下の例は、soundex()
関数の使用方法を示しています。
<?php
$str1 = "Ashcraft";
$str2 = "Ashcraft";
$str3 = "Ashcraft Jr.";
$soundex1 = soundex($str1);
$soundex2 = soundex($str2);
$soundex3 = soundex($str3);
echo "Ashcraft の Soundex コード: $soundex1\n";
echo "Ashcraft の Soundex コード: $soundex2\n";
echo "Ashcraft Jr. の Soundex コード: $soundex3\n";
?>
このコードを実行すると、次の出力が表示されます。
Ashcraft の Soundex コード: A-261
Ashcraft の Soundex コード: A-261
Ashcraft Jr. の Soundex コード: A-261
上記の例では、Ashcraft
と Ashcraft Jr.
は同じ発音であるため、同じ Soundex コードが生成されます。
Soundex の応用例
Soundex は、さまざまなアプリケーションで使用できます。以下に、いくつかの例を示します。
- 言語学研究: Soundex を使用して、さまざまな言語の音声パターンを研究することができます。
Soundex の制限
Soundex は、完全な発音インデックスではありません。いくつかの制限があります。
- Soundex は、頭文字が異なる単語を一致させることができません。たとえば、"Ashcraft" と "Craft" は異なる Soundex コードを持っています。
- Soundex は、発音が似ているすべての単語を一致させるわけではありません。たとえば、"Ashcraft" と "Eisencraft" は同じ Soundex コードを持っていますが、発音は異なります。
- Soundex は英語でのみ機能します。他の言語には、独自の Soundex アルゴリズムが必要になる場合があります。
<?php
function soundex($str) {
// 文字列を大文字に変換
$str = strtoupper($str);
// 文字列の先頭文字を抽出
$firstChar = $str[0];
// 残りの文字列を処理
$remainingChars = substr($str, 1);
$encodedChars = "";
// 各文字をエンコード
for ($i = 0; $i < strlen($remainingChars); $i++) {
$ch = $remainingChars[$i];
$encodedChar = encodeChar($ch);
// 同じ音節コードが連続する場合は、最初のコードのみを残す
if ($i > 0 && $encodedChar == $encodedChars[strlen($encodedChars) - 1]) {
continue;
}
$encodedChars .= $encodedChar;
}
// コードが 4 文字に達するまでエンコードを続ける
while (strlen($encodedChars) < 4) {
$encodedChars .= "0";
}
// 先頭文字とエンコードされた文字列を結合して Soundex コードを返す
return $firstChar . $encodedChars;
}
function encodeChar($ch) {
switch ($ch) {
case "A":
case "E":
case "I":
case "O":
case "U":
return "";
case "B":
case "F":
case "P":
return "1";
case "C":
case "G":
case "J":
case "K":
case "Q":
case "S":
case "X":
return "2";
case "D":
case "T":
return "3";
case "L":
return "4";
case "M":
case "N":
return "5";
case "R":
return "6";
case "V":
return "8";
case "W":
if ($i > 0 && $encodedChars[strlen($encodedChars) - 1] != "7") {
return "7";
}
break;
case "Y":
if ($i > 0 && $encodedChars[strlen($encodedChars) - 1] != "7") {
return "7";
}
break;
default:
return $ch;
}
}
// 例
$str1 = "Ashcraft";
$str2 = "Ashcraft";
$str3 = "Ashcraft Jr.";
$soundex1 = soundex($str1);
$soundex2 = soundex($str2);
$soundex3 = soundex($str3);
echo "Ashcraft の Soundex コード: $soundex1\n";
echo "Ashcraft の Soundex コード: $soundex2\n";
echo "Ashcraft Jr. の Soundex コード: $soundex3\n";
?>
Ashcraft の Soundex コード: A-261
Ashcraft の Soundex コード: A-261
Ashcraft Jr. の Soundex コード: A-261
Soundex の制限
- 頭文字が異なる単語を一致させることができません。
- すべての発音が似ている単語を一致させるわけではありません。
- 英語でのみ機能します。
これらの制限により、Soundex に代わるアルゴリズムを検討する必要がある場合があります。 Soundex の代替手段として検討すべきいくつかのオプションは次のとおりです:
NYSIIS
NYSIIS (New York State Identification System for Indexing) は、Soundex に似たアルゴリズムですが、より多くの言語をサポートし、より正確な結果を生成するように設計されています。 NYSIIS は、主に姓の索引付けに使用されます。
Metaphone
Metaphone は、もう 1 つの発音インデックス アルゴリズムで、Soundex よりも正確で、より多くの言語をサポートするように設計されています。 Metaphone は、特に姓の綴り間違いの修正に役立ちます。
Phonex
Phonex は、3 番目の発音インデックス アルゴリズムで、Soundex や Metaphone よりもシンプルで、処理速度が速くなります。 Phonex は、主に姓の索引付けに使用されます。
Double Metaphone
Double Metaphone は、Metaphone の改良版であり、より正確で包括的な結果を生成するように設計されています。 Double Metaphone は、特に姓の綴り間違いの修正に役立ちます。
コードウェイ
Codeway は、発音に基づいた文字列の索引付けに使用できる別のアルゴリズムです。 Codeway は、Soundex、Metaphone、Phonexよりもシンプルで、処理速度が速くなります。
最適なアルゴリズムの選択
使用するのに最適なアルゴリズムは、特定のニーズによって異なります。 考慮すべき要素には、次のものがあります。
- アプリケーション
- 処理速度
- 必要とされる精度
- サポートされている言語