我正在进行临床消息标准化(拼写检查),其中我根据 900,000 字的医学词典检查每个给定的单词。我更关心时间复杂度/性能。
我想做模糊字符串比较,但我不确定使用哪个库。
选项 1:
import Levenshtein
Levenshtein.ratio('hello world', 'hello')
Result: 0.625
选项2:
import difflib
difflib.SequenceMatcher(None, 'hello world', 'hello').ratio()
Result: 0.625
在这个例子中,两者给出了相同的答案。您认为在这种情况下两者的表现相似吗?
如果您对 Levenshtein 和 Difflib 相似性的快速视觉比较感兴趣,我计算了这两者的大约 230 万本书名:
import codecs, difflib, Levenshtein, distance
with codecs.open("titles.tsv","r","utf-8") as f:
title_list = f.read().split("\n")[:-1]
for row in title_list:
sr = row.lower().split("\t")
diffl = difflib.SequenceMatcher(None, sr[3], sr[4]).ratio()
lev = Levenshtein.ratio(sr[3], sr[4])
sor = 1 - distance.sorensen(sr[3], sr[4])
jac = 1 - distance.jaccard(sr[3], sr[4])
print diffl, lev, sor, jac
然后我用 R 绘制结果:
出于好奇,我还比较了 Difflib、Levenshtein、Sørensen 和 Jaccard 相似度值:
library(ggplot2)
require(GGally)
difflib <- read.table("similarity_measures.txt", sep = " ")
colnames(difflib) <- c("difflib", "levenshtein", "sorensen", "jaccard")
ggpairs(difflib)
结果:
Difflib / Levenshtein 的相似性确实非常有趣。
2018 年编辑:如果您正在努力识别相似的字符串,您还可以查看 minhashing——这里有一个很棒的概述。 Minhashing 在线性时间内查找大型文本集合中的相似性方面非常出色。我的实验室开发了一个应用程序,可以使用 minhashing 来检测和可视化文本重用:https://github.com/YaleDHLab/intertext
difflib.SequenceMatcher 使用 Ratcliff/Obershelp 算法,它计算匹配字符的双倍数量除以两个字符串中的字符总数。
Levenshtein 使用 Levenshtein 算法 它计算将一个字符串转换为另一个字符串所需的最小编辑次数
复杂性
SequenceMatcher 是最坏情况下的二次时间,并且其预期情况行为以复杂的方式依赖于序列有多少共同元素。 (从这里开始)
Levenshtein 的复杂度为 O(m*n),其中 n 和 m 是两个输入字符串的长度。
性能
根据Levenshtein模块的源代码: Levenshtein 与 difflib (SequenceMatcher) 有一些重叠。它仅支持字符串,不支持任意序列类型,但另一方面它速度更快。