假设我有一个string
"Hello"
和一个列表
words = ['hello', 'Hallo', 'hi', 'house', 'key', 'screen', 'hallo','question', 'Hallo', 'format']
如何找到最接近n words
并出现在"Hello"
列表中的words
?
在这种情况下,我们会['hello', 'hallo', 'Hallo', 'hi', 'format'...]
因此,策略是将列表单词从最接近的单词排序到最远的单词。
我想过这样的事情
word = 'Hello'
for i, item in enumerate(words):
if lower(item) > lower(word):
...
但是在大型名单中它很慢。
更新
difflib
有效,但也很慢。 (words list
里面有630000+个单词(已排序,每行一个))。因此,每次搜索最接近的单词时,检查列表需要5到7秒!
答案 0 :(得分:72)
>>> words = ['hello', 'Hallo', 'hi', 'house', 'key', 'screen', 'hallo', 'question', 'format']
>>> difflib.get_close_matches('Hello', words)
['hello', 'Hallo', 'hallo']
请查看文档,因为该函数默认返回3个或更少的最接近匹配。
答案 1 :(得分:22)
Peter Norvig提供了一篇关于拼写修正的完整源代码(21行)的精彩文章。
http://norvig.com/spell-correct.html
我们的想法是建立所有可能的单词编辑,
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)
现在,在列表中查找每个编辑内容。
彼得的文章很精彩,值得一读。
答案 2 :(得分:1)
创建单词的排序列表,并使用bisect module根据排序顺序识别排序列表中您的单词所适合的点。根据该位置,您可以给上面和下面的k个最近邻居找到2k个最接近的单词。
答案 3 :(得分:0)
也许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)
答案 4 :(得分:0)
我正在寻找这个答案,以便从列表中找到最接近的匹配项或...的可能替代方案
difflib.get_close_matches
我找到了Amjith's answer based on Peter Norwig's post,并认为它可能是一个很好的替代品。在我意识到它可能不太适合我的用例之前,我已经对它进行了分类。因此,这是拼写的一种版本,您可以在其中使用它来使用不同的单词集。也许最好用于人口名称匹配。
import re
from collections import Counter
def words(text): return re.findall(r'\w+', text.lower())
# WORDS = Counter(words(open('big.txt').read()))
class WordMatcher:
def __init__(self, big_text):
self.WORDS=Counter(words(big_text))
self.N = sum(self.WORDS.values())
def P(self, word):
"Probability of `word`."
return self.WORDS[word] / self.N
def correction(self, word):
"Most probable spelling correction for word."
return max(self.candidates(word), key=self.P)
def candidates(self, word):
"Generate possible spelling corrections for word."
return (self.known([word]) or self.known(self.edits1(word)) or self.known(self.edits2(word)) or [word])
def known(self, words):
"The subset of `words` that appear in the dictionary of WORDS."
return set(w for w in words if w in self.WORDS)
def edits1(self, word):
"All edits that are one edit away from `word`."
letters = 'abcdefghijklmnopqrstuvwxyz'
splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [L + R[1:] for L, R in splits if R]
transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]
replaces = [L + c + R[1:] for L, R in splits if R for c in letters]
inserts = [L + c + R for L, R in splits for c in letters]
return set(deletes + transposes + replaces + inserts)
def edits2(self, word):
"All edits that are two edits away from `word`."
return (e2 for e1 in self.edits1(word) for e2 in self.edits1(e1))