Python中比较两个大字符串集的最佳方式

6

我正在使用Python(并且可以访问pandas,numpy,scipy)。

我有两组字符串集A和集B。每个集合A和B包含大约2000个元素(每个元素都是一个字符串)。这些字符串长约50-100个字符,包含多达20个单词(这些集合可能会变得更大)。

我希望检查集合A的成员是否也是集合B的成员。

现在我考虑一个朴素的实现方式,可以将A和B中的成员进行比较,并将布尔值(0、1)从比较中构成矩阵(例如,A1 == B1,A1 == B2,A1 == B3等),该矩阵即为结果。

如何高效地实现这一目标?

进一步说明:

(i)对于更大的数据集,我考虑使用Bloom过滤器(例如使用PyBloom,pybloomfilter)对每个字符串进行哈希处理(即使有假阳性也无妨……)。这是否是一个好方法,或者是否有其他策略应该考虑?

(ii)我正在考虑在字符串之间包括Levenshtein距离匹配(我知道它可能很慢),因为我可能需要模糊匹配 - 是否有一种方法可以将其与(i)中的方法结合起来或以其他方式使其更有效?

提前感谢任何帮助!


6
seta & setb(或seta.intersection(setb))有什么问题? - mgilson
2
在Python中,set(就像dictionary)使用哈希来检查项目是否存在。这是大多数应用程序的有效方法。但是,这仅适用于_精确_匹配。不适用于_模糊_匹配。如果您计划使用某些算法,例如Levenshtein距离,则必须使用有效数据。而不是哈希。因此,这将是一个重要的性能下降。更不用说您将不得不计算第一组每个项目和第二组每个项目之间的距离。最好是O(n log n)? - Sylvain Leroux
你如何定义模糊匹配?根据定义,你可以使用后缀树或字典树。 - Rerito
3个回答

5

首先,2000 * 100个字符并不算太大,您可以直接使用set。

其次,如果您的字符串已经排序,有一种快速的方法(我在这里找到),如下所示进行比较:

def compare(E1, E2):
    i, j = 0, 0
    I, J = len(E1), len(E2)
    while i < I:
        if j >= J or E1[i] < E2[j]:
            print(E1[i], "is not in E2")
            i += 1
        elif E1[i] == E2[j]:
            print(E1[i], "is in E2")
            i, j = i + 1, j + 1
        else:
            j += 1

相比使用 set,这种方法肯定会更慢,但它不需要将字符串保留在内存中(每次只需要两个字符串)。

对于 Levenshtein 相关问题,你可以在 Pypi 上找到一个 C 模块,该模块速度非常快。


这是一个非常适用于有序数据的好解决方案。我对其进行了修改,使其可以在无序数据上运行,请查看我的答案,其中我复制了该函数。 - mit

2

如评论中所述:

def compare(A, B):
    return list(set(A).intersection(B))

0

这是函数的修改版本,@michaelmeyer在这里提供了https://dev59.com/e3PYa4cB1Zd3GeqPlqYa#17264117 - 他回答了我们所在页面顶部的问题。

下面的修改版本也适用于未排序的数据,因为该函数现在包括了排序功能。

在许多情况下,这不应该是性能或资源问题,因为Python排序非常有效。而且预先排序也有帮助。

请注意,“输出”现在也按排序顺序排列。如果第一个参数未排序,则与原始顺序不同。

否则,即使两个数据集都已排序,排序也不会对其造成太大影响。

但是,如果您想抑制排序(在两个数据集已知以升序排序的情况下),请像这样调用它:

compare(my_data1,my_data2,data_is_sorted=True)

否则:
compare(my_data1,my_data2)

而且该函数接受无序数据。

这是修改后的版本。只添加了前两行和一个可选的第三个参数:

def compare(E1, E2, data_is_sorted=False):
    if not data_is_sorted:
        E1=sorted(E1)
        E2=sorted(E2)
    i, j = 0, 0
    I, J = len(E1), len(E2)
    while i < I:
        if j >= J or E1[i] < E2[j]:
            print(E1[i], "is not in E2")
            i += 1
        elif E1[i] == E2[j]:
            print(E1[i], "is in E2")
            i, j = i + 1, j + 1
        else:
            j += 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接