python – 通过过滤生成不同(远距离,通过编辑距离)单词的列表
作者:互联网
我有一个很长的(> 1000项)单词列表,我希望从中删除与其他单词“太相似”的单词,直到剩下的单词都“显着不同”.例如,这样在编辑距离D内没有两个单词.
我不需要一个独特的解决方案,它不一定是最佳的,但它应该相当快(在Python中)并且不会丢弃太多条目.
我怎样才能做到这一点?谢谢.
编辑:要清楚,我可以google一个测量编辑距离的python例程.问题是如何有效地做到这一点,并且,或许,在某种程度上找到了D的“自然”价值.也许通过从所有单词构建某种类型的特里然后修剪?
解决方法:
您可以使用bk树,在添加每个项目之前检查它是否在任何其他项目的距离D内(感谢@DietrichEpp在此想法的评论中.
您可以将this recipe用于bk树(尽管可以轻松修改任何类似的配方).只需进行两项更改:更改行:
def __init__(self, items, distance, usegc=False):
至
def __init__(self, items, distance, threshold=0, usegc=False):
并改变线
if el not in self.nodes: # do not add duplicates
至
if (el not in self.nodes and
(threshold == None or len(self.find(el, threshold)) == 0)):
这样可确保在添加项目时不会出现重复项.然后,从列表中删除重复项的代码就是:
from Levenshtein import distance
from bktree import BKtree
def remove_duplicates(lst, threshold):
tr = BKtree(iter(lst), distance, threshold)
return tr.nodes.keys()
请注意,这依赖于python-Levenshtein包的距离函数,这比bk-tree提供的快得多. python-Levenshtein有C编译组件,但值得安装.
最后,我设置了一个性能测试,其中包含越来越多的单词(从/usr/share / dict / words中随机获取),并绘制了每次运行所花费的时间:
import random
import time
from Levenshtein import distance
from bktree import BKtree
with open("/usr/share/dict/words") as inf:
word_list = [l[:-1] for l in inf]
def remove_duplicates(lst, threshold):
tr = BKtree(iter(lst), distance, threshold)
return tr.nodes.keys()
def time_remove_duplicates(n, threshold):
"""Test using n words"""
nwords = random.sample(word_list, n)
t = time.time()
newlst = remove_duplicates(nwords, threshold)
return len(newlst), time.time() - t
ns = range(1000, 16000, 2000)
results = [time_remove_duplicates(n, 3) for n in ns]
lengths, timings = zip(*results)
from matplotlib import pyplot as plt
plt.plot(ns, timings)
plt.xlabel("Number of strings")
plt.ylabel("Time (s)")
plt.savefig("number_vs_time.pdf")
如果不以数学方式确认,我认为它不是二次的,我认为它实际上可能是n log n,如果插入bk-tree是一个日志时间操作,这将是有意义的.最值得注意的是,它运行速度非常快,不到5000个字符串,这有望成为OP的目标(15000是合理的,传统的for循环解决方案不会这样).
标签:duplicate-removal,edit-distance,python,algorithm,similarity 来源: https://codeday.me/bug/20190901/1782748.html