自动更正python中列表中的单词

时间:2019-04-30 13:17:30

标签: python python-3.x difflib autocorrect

我想自动更正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的值,它将开始返回不应该的单词。

因此,即使我计划创建给定句子的三字母组,也将花费大量时间。

那么有没有办法实现呢?

我探索了更多的库,例如autocorrecthunspell等,但是没有成功。

3 个答案:

答案 0 :(得分:2)

您可以实现基于levenshtein distance的东西。

值得注意的是elasticsearch的实现:https://www.elastic.co/guide/en/elasticsearch/guide/master/fuzziness.html

  

很显然,比伯离海狸还有很长的路要走,它们相距太远而无法   被认为是简单的拼写错误。 Damerau观察到80%的人类   拼写错误的编辑距离为1。换句话说,80%的   只需对原始内容进行一次修改,即可纠正拼写错误   字符串。

     

Elasticsearch支持最大编辑距离,该距离由   模糊参数,为2。

     

当然,一次编辑对字符串的影响取决于   字符串的长度。帽子一词的两次修改会产生疯狂的后果,   因此,允许对长度为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)

只需确保使用更好的令牌生成器,否则会很混乱,但是您明白了。另请注意,这是未优化的,并且在使用许多关键字的情况下会非常缓慢。您应该实现某种存储方式,以使所有单词与所有关键字都不匹配。

答案 1 :(得分:2)

这是使用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'] 

答案 2 :(得分:1)

尽管这与您的预期输出略有不同(它是列表列表而不是字符串列表),但我认为这是朝着正确方向迈出的一步。我选择此方法的原因是,您可以对每个句子进行多次更正。这就是为什么我添加了另一个例句的原因。

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']]

诀窍是沿空格将所有句子分开。