簡単な音声検索の実装例

問題文



旅行者のパスポートに記録されているように、英語表記のロシア語とウクライナ語の名前のリストを含むデータベースがあります。 少し前にロシアのこれらのパスポートの転記規則が変更されたため(英語からフランス語へのトリ、逆にトリ)、任意の名前を異なる方法で書くことができるという非常に現実的かつ公式な可能性さえあります。 さらに、データは海のパスポートから取得されることがあるため、状況がさらに混乱します。

このデータベースで、姓、たとえばShcheglovなどの人物をすばやく見つける必要があると想像してみてください(笑)



ソリューションオプション



既存のアルゴリズムは、純粋な英語へのオリエンテーションによっても、「ホットサーチ」の完全な不可能性によっても好まれていませんでした(姓を完全に入力してから比較する必要があります)。 そして、ギリシャのプロジェクトのために何年も前に書いた、かなり単純なアルゴリズムを思い出しました。同様の問題はさらに厳しいものでした。そこにある(ギリシャ語)演算子の名前は電話で聞かなければなりませんでした。 アルゴリズムの説明は、当時の仲間から「voel」と呼ばれていました。 もちろん、ギリシャ語とロシア語はあまり似ていませんが、転写されたシリアルは非常に似ているため、前述の「声」をロシア語のニーズに変えるリスクを負うことにしました。





いくつかの必要な説明



何年も前-太陽が明るく、草がより緑で、少女たちがより神秘的で、これらの行の著者であるRADという言葉について厚い本が書かれていました。

それ以来、特に多くの変化がありました。特に、著者の職業は長年にわたってIT全般、特にプログラミングに関連付けられていませんでした。 退屈な人事管理、灰色のオフィスの平日。

しかし、彼らはプログラマーは以前ではない、とオフィスを移動することに関連してペーパーレス書類への切り替えについての質問が生じたとき、ニーズがかなり控えめなので、私はシステムを書くことに挑戦しました。

私の意見では、良い批判と貴重なコメントへのささやかな希望を共有するために私がベンチャーしたプロジェクトのいくつかの興味深いおよび/または物議を醸す部分。

だから、「ゴールドフィンチ」。



提案されたソリューション



一般に、言及された「voel」は非常に単純なことを行いました:単語全体を1つのレジスタに変換し、たとえば小文字に変換し、一部の文字または文字の組み合わせを「音声一致」、つまり単純に他の文字に置き換えます(ほとんどの場合-組み合わせ)。

ロシア語の「音声通信」の同様のテーブルを作成しようとしましたが、次のようなものを得ました(コメントは大歓迎です):



まず、あらゆる種類の二重子音。 削除します、1つで十分です:

bb = b kk = k rr = r
cc = c ll = l ss = s
dd = d mm = m tt = t
ff = v nn = n zz = z
hh = h pp = p




次-さまざまなシューという音:

sh = s zch = s ck = k
ch = c sch = s ks = x
shch = s csh = s ts = c
zhch = s zh = z tc = c




次に、「y」、「I」、「e」、「y」、「f」など、ロシア語の残りの独自機能:

yu = u je = e oy = oi
ju = u ei = ei oj = oi
u = u ey = ei ph = f
ya = a ej = ei yy = i
ja = a yo = e ii = i
ia = a io = e iy = i
ye = e jo = e y = i
すなわち= e oi = oi yy = i




まあなど、残り:

kh = h gh = g '=




つまり、前述のScheglovが「Shcheglov」、「Scheglov」、または「Zchegloff」と書かれていても、この表の助けを借りて明確な「seglov」に翻訳されます。

コードを書くことは残っています。



クラスtvoel



以下の例では、Delphiを使用しています。

コレスポンデンステーブルは、ファイルからTStringList型のシートに読み込まれ、バイナリ検索用にソートされます。 Locate関数はこの検索を実行します。 対応する関数の実装は、一般的には省略されています。



type TVoel = class private FFileName: String; FList: TStrings; procedure setFileName(const Value: String); procedure readFile; function isReady: Boolean; function Locate(const Value: String; var Index: Integer): Boolean; public constructor Create; destructor Destroy; override; function Convert(const Value: String): String; property FileName: String read FFileName write SetFileName; end; implementation function TVoel.Convert(const Value: String): String; var ii, p, len: Integer; str: String; Ch: String; found: Boolean; begin Result := ''; len := Length(Value); ii := 0; while ii < len do begin Inc(ii); Ch := Value[ii]; found := Locate(Ch, p); if found then begin str := Value[ii]; while found and (ii < len) do begin Inc(ii); str := str + Value[ii]; found := Locate(str, p); end; if not found then begin setlength(str, length(str)-1); Dec(ii); end; if CompareText(str, FList.Names[p]) = 0 then Ch := FList.ValueFromIndex[p]; end; Result := Result + Ch; end; Result := ANSIUpperCase(Result); end;
      
      







現時点では、上記のクラスを使用して、数万人の控えめなリストの「表音表」を「デバッグ」しています。 もちろん、最終的な実装は、データベースに組み込まれたプロシージャとして記述される必要があります。



All Articles