自动更正python列表中的单词

Posted

技术标签:

【中文标题】自动更正python列表中的单词【英文标题】:auto-correct the words from the list in python 【发布时间】:2019-09-19 04:00:08 【问题描述】:

我想自动更正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 等,但没有成功。

【问题讨论】:

【参考方案1】:

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

注意elasticsearch的实现很有意思:https://www.elastic.co/guide/en/elasticsearch/guide/master/fuzziness.html

显然,比伯与海狸相差甚远——他们相距甚远 被认为是一个简单的拼写错误。 Damerau 观察到 80% 的人类 拼写错误的编辑距离为 1。换句话说,80% 拼写错误可以通过对原文的一次编辑来纠正 字符串。

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

当然,单个编辑对字符串的影响取决于 字符串的长度。对帽子这个词的两次编辑可以产生疯狂, 所以允许对长度为 3 的字符串进行两次编辑是多余的。这 fuzziness参数可以设置为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)

只要确保使用更好的标记器,否则会变得一团糟,但你明白了。另请注意,这是未优化的,并且在使用大量关键字时会非常慢。您应该实施某种分桶以不将所有单词与所有关键字匹配。

【讨论】:

感谢您提供有用的信息。将检查我的真实数据的性能。【参考方案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'] 

【讨论】:

恐怕这太慢了。实际上,我正在为聊天机器人实现它,所以速度对我来说很重要。【参考方案3】:

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

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

诀窍是沿着空格分割所有句子。

【讨论】:

在我的情况下不起作用,因为我的 kw 列表可能包含多个单词,如果我在空白处拆分,它不会给出正确的结果。

以上是关于自动更正python列表中的单词的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS8自定义键盘中使用自动更正和快捷列表?

在Python中随机反转列表列表中的一半单词

python Python - 列表中的单词

解析python中的单词列表

删除列表中包含部分单词的 Python 列表中的元素

python中的单词聚类列表