string
"Hello"
とリストがあるとしましょう
words = ['hello', 'Hallo', 'hi', 'house', 'key', 'screen', 'hallo','question', 'Hallo', 'format']
n words
に最も近く、リストwords
にある"Hello"
を見つけるにはどうすればよいですか?
この場合、['hello', 'hallo', 'Hallo', 'hi', 'format'...]
になります
したがって、戦略は、リストの単語を最も近い単語から最も遠い単語に並べ替えることです。
私はこのようなことを考えました
Word = 'Hello'
for i, item in enumerate(words):
if lower(item) > lower(Word):
...
しかし、大きなリストでは非常に遅くなります。
[〜#〜] update [〜#〜]difflib
は動作しますが、非常に遅いです。 (words list
には、630000以上の単語が含まれています(ソートされ、1行に1つ))。そのため、最も近いWordを検索するたびに、リストの確認に5〜7秒かかります。
つかいます - difflib.get_close_matches
。
>>> words = ['hello', 'Hallo', 'hi', 'house', 'key', 'screen', 'hallo', 'question', 'format']
>>> difflib.get_close_matches('Hello', words)
['hello', 'Hallo', 'hallo']
この関数はデフォルトで3以下の最も近い一致を返すため、ドキュメントをご覧ください。
スペル修正に関するPeter Norvigから提供された完全なソースコード(21行)を含む素晴らしい記事があります。
http://norvig.com/spell-correct.html
考えは、Wordの可能なすべての編集を構築することです。
hello - helo - deletes
hello - helol - transpose
hello - hallo - replaces
hello - heallo - inserts
def edits1(Word):
splits = [(Word[:i], Word[i:]) for i in range(len(Word) + 1)]
deletes = [a + b[1:] for a, b in splits if b]
transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1]
replaces = [a + c + b[1:] for a, b in splits for c in alphabet if b]
inserts = [a + c + b for a, b in splits for c in alphabet]
return set(deletes + transposes + replaces + inserts)
次に、リストでこれらの編集のそれぞれを調べます。
ピーターの記事は素晴らしい読み物であり、読む価値があります。
単語のソート済みリストを作成し、 bisect module を使用して、ソート順に従ってWordが収まるソート済みリスト内のポイントを識別します。その位置に基づいて、2 k個の最も近い単語を見つけるために、上下のk個の最近傍を指定できます。
多分 heap はあなたを助けることができます。
Heap
という名前のヒープがあり、サイズがn
より小さくなるまで、関数Heap
を使用してclose
に単語を挿入します[この文字列が近いことを示します別の文字列よりも]。
このメソッドは、n
が小さいときに役立ちます:)
Heap = []
for Word in words:
if len(Heap)<n:
Heap.insert(Word)
else
if close(Word,Heap[0]): # it means Heap[0] is the nth farthest Word until now
Heap.pop():
Heap.insert(Word)