我有一个包含27,000个字符串的大型列表,我必须找到哪两个字符串相似。为此,我使用这个python库 - Levenshtein Library来查找2个字符串之间的相似性。使用以下代码,这是直截了当的
count - 0
for i, coll1 in enumerate(college_list):
for j, coll2 in enumerate(college_list):
if abs(len(coll1) - len(coll2)) <= 15:
similarity = jaro(coll1,coll2)
if similarity >= 0.90 and similarity != 1.0 and :
print "Probable Similar Strings"
print coll1 + " AND " + coll2
print "Similarity is %s" % (similarity)
print "=" * 20
count += 1
但正如您所看到的那样,它们是2个for循环,可将一个字符串与另一个字符串进行比较,此类组合的总数 729000000 (27000 X 27000)。
我目前的代码需要花费大量时间才能完成,我必须改变相似度阈值才能达到适合我用例的结果。运行具有不同相似性阈值的此代码的多次迭代肯定会花费大量时间
使用numpy / pandas是否存在更好,更快捷的方式来实现上述功能
答案 0 :(得分:3)
在考虑转换为numpy之前,我认为你应该只计算j&lt;如果Levenshtein相似性是一个双射,它将需要计算的一半。
参见下面的例子:如果jaro(“aa”,“aa”)== 1,则不需要计算所有“/” 和jaro(“ab”,“aa”)== jaro(“aa”,“ab”)。
i/j aa ab ac
aa / 1 1
ab / / 1
ac / / /
答案 1 :(得分:3)
您正在寻找itertools,它通过使用效率更高的生成器为您解决循环问题。
itertools。组合也确保不会反向生成相同的对。
combinations('ABCD', 2)
AB AC AD BC BD CD
看到没有BA
或DA
,因为AB
和AD
已经存在。
如你所见,我完全放弃了字符串长度比较。仅仅因为我没有看到有很多两个名字长度如此不同。我使用this random name generator生成了一些示例,但它从未发生过。
即使它会发生几次,if也会花费很多其他行,这可能不值得。更不用说它会产生极长字符串的不良行为。
我在这里为你做了一个小例子:
import itertools
import Levenshtein
college_list = ['Dave', 'Jack', 'Josh', 'Donald', 'Carry', 'Kerry', 'Cole', 'Coal', 'Coala']
for pair in itertools.combinations(college_list, 2):
similarity = Levenshtein.jaro(pair[0], pair[1])
if similarity >= 0.90 and similarity != 1.0:
print pair, similarity
返回
('Coal', 'Coala') 0.933333333333
答案 2 :(得分:2)
为了添加建议的改进,我建议您先按长度排序college_list
,然后仅计算长度不同<= 15
的单词的Levenshtein相似度。像
from Levenshtein import jaro
college_list.sort(key=len)
for i, coll1 in enumerate(college_list):
for j in xrange(i + 1, len(college_list)):
coll2 = college_list[j]
if len(coll2) - len(coll1) > 15:
break
similarity = jaro(coll1,coll2)
if similarity >= 0.90 and similarity != 1.0:
print "Probable Similar Strings"