使用Python中的difflib包进行近似字符串匹配,考虑删除操作

172 阅读2分钟

在Python中,我们可以使用difflib库来进行字符串相似性匹配。但是,默认情况下,difflib.get_close_matches()函数不考虑删除操作,因此对于某些情况,可能无法得到预期的结果。

例如:

from difflib import get_close_matches as gcm

x = """Erfreulich
Erfreuliche
Erfreulicher
Erfreulicherem
Erfreulicheres
Erfreulicherweis
Erfreulicherweise
Erfreuliches
Erfreulichste"""

x = [i for i in x.split("\n")]

for i in x:
  print(i, gcm(i, x))

输出结果:

Erfreulich ['Erfreulich', 'Erfreuliche', 'Erfreuliches']
Erfreuliche ['Erfreuliche', 'Erfreuliches', 'Erfreulicher']
Erfreulicher ['Erfreulicher', 'Erfreuliche', 'Erfreulicheres']
Erfreulicherem ['Erfreulicherem', 'Erfreulicheres', 'Erfreulicher']
Erfreulicheres ['Erfreulicheres', 'Erfreulicherweis', 'Erfreulicherem']
Erfreulicherweis ['Erfreulicherweis', 'Erfreulicherweise', 'Erfreulicheres']
Erfreulicherweise ['Erfreulicherweise', 'Erfreulicherweis', 'Erfreulicheres']
Erfreuliches ['Erfreuliches', 'Erfreuliche', 'Erfreulicheres']
Erfreulichste ['Erfreulichste', 'Erfreuliche', 'Erfreuliches']

可以看到,对于字符串“Erfreulicher”,虽然与“Erfreulich”的Levenshtein距离仅为-1,但“Erfreulich”却没有被认为是“Erfreulicher”的近似匹配。

  1. 解决方案

为了解决这个问题,我们可以通过以下方法:

  • **增加n参数的值:**difflib.get_close_matches()函数的n参数指定了要返回的近似匹配数量,默认值为3。我们可以通过增加n参数的值来得到更多近似匹配。

例如:

from difflib import get_close_matches as gcm

x = """Erfreulich
Erfreuliche
Erfreulicher
Erfreulicherem
Erfreulicheres
Erfreulicherweis
Erfreulicherweise
Erfreuliches
Erfreulichste"""

x = [i for i in x.split("\n")]

for i in x:
  print(i, gcm(i, x, 6))

输出结果:

Erfreulicher ['Erfreulicher', 'Erfreuliche', 'Erfreulicheres', 'Erfreulicherem',              'Erfreuliches', 'Erfreulich']

可见,通过增加n参数的值,我们可以得到更多的近似匹配,其中就包括了“Erfreulich”。

  • **使用SequenceMatcher类:**difflib库还提供了一个叫做SequenceMatcher的类,我们可以使用这个类来计算两个字符串之间的相似性得分。相似性得分的范围是0.0到1.0,值越大表示两个字符串越相似。

例如:

import difflib

s = difflib.SequenceMatcher()
s.set_seq2("Erfreulicher")

full = []
for i in x:
    s.set_seq1(i)
    full.append((s.ratio(), i))

full.sort(reverse=True)
for score, i in full:
    print("{:20} {:.3f}".format(i, score))

输出结果:

Erfreulicher         1.000
Erfreuliche          0.957
Erfreulicheres       0.923
Erfreulicherem       0.923
Erfreuliches         0.917
Erfreulich           0.909
Erfreulichste        0.880
Erfreulicherweis     0.857
Erfreulicherweise    0.828

通过对相似性得分进行排序,我们可以得到最相似的几个字符串。

  • **使用Levenshtein距离:**Levenshtein距离是衡量两个字符串之间差异的一种方法,计算方法是将一个字符串转换为另一个字符串所需的最小编辑操作次数(插入、删除、替换)。我们可以使用Python中的levenshtein包来计算两个字符串之间的Levenshtein距离。

例如:

from Levenshtein import distance

distance("Erfreulicher", "Erfreulich")

输出结果:

1

可见,“Erfreulicher”和“Erfreulich”之间的Levenshtein距离为1。

通过计算Levenshtein距离,我们可以找到与目标字符串差异最小的几个字符串。