我正在寻找一个Python模块,可以做简单的模糊字符串比较。具体来说,我想知道字符串相似程度的百分比。我知道这是潜在的主观,所以我希望找到一个库,可以做位置比较以及最长的相似字符串匹配,等等。

基本上,我希望找到一些足够简单的东西,可以产生单个百分比,同时仍然可以配置,以便我可以指定要进行哪种类型的比较。


当前回答

Difflib可以做到。

文档中的例子:

>>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'])
['apple', 'ape']
>>> import keyword
>>> get_close_matches('wheel', keyword.kwlist)
['while']
>>> get_close_matches('apple', keyword.kwlist)
[]
>>> get_close_matches('accept', keyword.kwlist)
['except']

来看看。它还有其他功能,可以帮助您定制一些东西。

其他回答

我喜欢诺斯克洛的回答;另一种方法是Damerau-Levenshtein距离:

在信息理论和计算机科学中,Damerau-Levenshtein距离是两个字符串之间的“距离”(字符串度量),即有限的符号序列,通过计算将一个字符串转换为另一个字符串所需的最小操作次数来给出,其中一个操作被定义为单个字符的插入、删除或替换,或两个字符的转位。

来自Wikibooks的Python实现:

def lev(a, b):
    if not a: return len(b)
    if not b: return len(a)
    return min(lev(a[1:], b[1:])+(a[0] != b[0]), \
    lev(a[1:], b)+1, lev(a, b[1:])+1)

更多内容来自维基百科, 这给出了最长公共子串(LCS)的长度:

def LCSubstr_len(S, T):
    m = len(S); n = len(T)
    L = [[0] * (n+1) for i in xrange(m+1)]
    lcs = 0
    for i in xrange(m):
        for j in xrange(n):
            if S[i] == T[j]:
                L[i+1][j+1] = L[i][j] + 1
                lcs = max(lcs, L[i+1][j+1])
    return lcs

我一直在用座位极客的Fuzzy Wuzzy,而且非常成功。

https://github.com/seatgeek/fuzzywuzzy

具体来说,令牌集比率函数…

他们还写了一篇关于模糊字符串匹配过程的文章:

http://seatgeek.com/blog/dev/fuzzywuzzy-fuzzy-string-matching-in-python

Levenshtein Python扩展和C库。

https://github.com/ztane/python-Levenshtein/

Levenshtein Python C扩展模块包含用于快速的函数 计算 - Levenshtein(编辑)距离,编辑操作 -字符串相似度 -近似中值字符串,通常字符串平均 -字符串序列和集相似度 它支持普通字符串和Unicode字符串。

$ pip install python-levenshtein
...
$ python
>>> import Levenshtein
>>> help(Levenshtein.ratio)
ratio(...)
    Compute similarity of two strings.

    ratio(string1, string2)

    The similarity is a number between 0 and 1, it's usually equal or
    somewhat higher than difflib.SequenceMatcher.ratio(), becuase it's
    based on real minimal edit distance.

    Examples:
    >>> ratio('Hello world!', 'Holly grail!')
    0.58333333333333337
    >>> ratio('Brian', 'Jesus')
    0.0

>>> help(Levenshtein.distance)
distance(...)
    Compute absolute Levenshtein distance of two strings.

    distance(string1, string2)

    Examples (it's hard to spell Levenshtein correctly):
    >>> distance('Levenshtein', 'Lenvinsten')
    4
    >>> distance('Levenshtein', 'Levensthein')
    2
    >>> distance('Levenshtein', 'Levenshten')
    1
    >>> distance('Levenshtein', 'Levenshtein')
    0

我用的是双变音位,就像一个咒语。

一个例子:

>>> dm(u'aubrey')
('APR', '')
>>> dm(u'richard')
('RXRT', 'RKRT')
>>> dm(u'katherine') == dm(u'catherine')
True

更新: 水母也有。在语音编码下。

另一种选择是使用最近发布的软件包FuzzyWuzzy。本博客还介绍了包支持的各种功能。