在集合中查找类似字符串的优化方法

时间:2015-05-26 12:30:10

标签: python numpy pandas

我有一个包含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是否存在更好,更快捷的方式来实现上述功能

3 个答案:

答案 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

看到没有BADA,因为ABAD已经存在。

如你所见,我完全放弃了字符串长度比较。仅仅因为我没有看到有很多两个名字长度如此不同。我使用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"