我想自动纠正我的list
中的单词。
说我有一个清单
kw = ['tiger','lion','elephant','black cat','dog']
我想检查这句话是否出现在我的句子中。如果拼写错误,我想纠正它们。我不打算触摸除给定列表之外的其他单词。
现在我有str
的列表
s = ["I saw a tyger","There are 2 lyons","I mispelled Kat","bulldogs"]
预期产量:
['tiger','lion',None,'dog']
我的努力:
import difflib
op = [difflib.get_close_matches(i,kw,cutoff=0.5) for i in s]
print(op)
我的输出:
[[], [], [], ['dog']]
上面代码的问题是我要比较整个句子,我的kw
列表可以有超过1个单词(最多4-5个单词)。
如果我降低cutoff
值,它会开始返回不应该的单词。
因此,即使我计划创建双字母组合,来自给定句子的三元组也会耗费大量时间。
有没有办法实现这个?
我已经探索了更多的图书馆,如autocorrect
,hunspell
等,但没有成功。
你可以实现基于levenshtein distance
的东西。
注意elasticsearch的实现是有趣的:https://www.elastic.co/guide/en/elasticsearch/guide/master/fuzziness.html
显然,比伯离海狸还有很长的路要走 - 他们相距太远而不能被视为简单的拼写错误。 Damerau观察到80%的人类拼写错误的编辑距离为1.换句话说,80%的拼写错误可以通过对原始字符串进行一次编辑来纠正。
Elasticsearch支持使用模糊参数指定的最大编辑距离2。
当然,单个编辑对字符串的影响取决于字符串的长度。单词hat的两个编辑可以产生疯狂,因此允许对长度为3的字符串进行两次编辑是过度的。模糊参数可以设置为AUTO,这会产生以下最大编辑距离:
0表示一个或两个字符的字符串
1表示三个,四个或五个字符的字符串
2表示超过五个字符的字符串
我喜欢自己使用pyxDamerauLevenshtein。
pip install pyxDamerauLevenshtein
所以你可以做一个简单的实现,如:
keywords = ['tiger','lion','elephant','black cat','dog']
from pyxdameraulevenshtein import damerau_levenshtein_distance
def correct_sentence(sentence):
new_sentence = []
for word in sentence.split():
budget = 2
n = len(word)
if n < 3:
budget = 0
elif 3 <= n < 6:
budget = 1
if budget:
for keyword in keywords:
if damerau_levenshtein_distance(word, keyword) <= budget:
new_sentence.append(keyword)
break
else:
new_sentence.append(word)
else:
new_sentence.append(word)
return " ".join(new_sentence)
只要确保你使用一个更好的标记器,否则这将变得混乱,但你明白了。另请注意,这是未经优化的,并且对于很多关键字来说会非常慢。您应该实现某种类型的分组,以使所有关键字都不匹配。
这是使用difflib.SequenceMatcher
的一种方式。 SequenceMatcher
类允许您使用ratio
方法测量句子相似度,您只需要提供一个合适的阈值,以保持比率高于给定阈值的单词:
def find_similar_word(s, kw, thr=0.5):
from difflib import SequenceMatcher
out = []
for i in s:
f = False
for j in i.split():
for k in kw:
if SequenceMatcher(a=j, b=k).ratio() > thr:
out.append(k)
f = True
if f:
break
if f:
break
else:
out.append(None)
return out
产量
find_similar_word(s, kw)
['tiger', 'lion', None, 'dog']
虽然这与您的预期输出略有不同(它是列表而不是字符串列表)但我认为这是向正确方向迈出的一步。我选择这种方法的原因是你可以对每个句子进行多次修正。这就是我添加另一个例句的原因。
import difflib
import itertools
kw = ['tiger','lion','elephant','black cat','dog']
s = ["I saw a tyger","There are 2 lyons","I mispelled Kat","bulldogs", "A tyger is different from a doog"]
op = [[difflib.get_close_matches(j,kw,cutoff=0.5) for j in i.split()] for i in s]
op = [list(itertools.chain(*o)) for o in op]
print(op)
生成的输出是:
[['tiger'], ['lion'], [], ['dog'], ['tiger', 'dog']]
诀窍是将所有句子沿着空格分开。