【问题标题】:Best way to compare two large sets of strings in Python在 Python 中比较两组大字符串的最佳方法
【发布时间】:2013-06-20 06:09:09
【问题描述】:

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

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

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

现在我认为可以将一个简单的实现可视化为一个矩阵,其中 A 和 B 中的成员相互比较(例如 A1 == B1、A1 == B2、A1 == B3 等等......)比较中的布尔值 (0, 1) 包含矩阵的元素。

什么是有效实现这一点的最佳方法?

两个进一步的阐述:

(i) 我也在想,对于更大的集合,我可以使用 Bloom Filter(例如使用 PyBloom、pybloomfilter)来散列每个字符串(即,我不太介意 fasle positives ......)。这是一个好方法还是我应该考虑其他策略?

(ii) 我正在考虑在字符串之间加入 Levenshtein 距离匹配(我知道这可能很慢),因为我可能需要模糊匹配 - 有没有办法将它与 (i) 中的方法结合起来,或者以其他方式制作它效率更高?

提前感谢您的帮助!

【问题讨论】:

  • seta & setb(或seta.intersection(setb))有什么问题
  • 在 Python 中 set(如 dictionary)使用哈希来检查项目是否存在。对于大多数应用程序来说,这是一种有效的方法。但是,这仅适用于 exact 匹配。不适用于 fuzzy 匹配。如果您打算使用像Levenshtein distance 这样的算法,您将不得不使用有效数据。不是哈希。所以这将是一个重要的性能下降。更不用说您必须计算第一组的每个项目与第二组的每个项目之间的距离。 O(n log n) 最多?。
  • 如何定义模糊匹配?根据定义,您可以使用后缀树或尝试。

标签: python string bloom-filter


【解决方案1】:

这是@michaelmeyer 在此处https://stackoverflow.com/a/17264117/362951 提出的函数的修改版本 - 在他对我们所在页面顶部问题的回答中。

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

这在很多情况下不应该是性能或资源问题,因为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

【讨论】:

    【解决方案2】:

    如 cmets 中所述:

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

    【讨论】:

      【解决方案3】:

      首先,2000 * 100 个字符并没有那么大,你可以直接使用一个集合。

      其次,如果你的字符串是排序的,有一个快速的方法(我找到here)来比较它们,如下:

      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
      

      它肯定比使用集合要慢,但它不需要将字符串保存到内存中(同时只需要两个)。

      对于 Levenshtein,有一个 C 模块,你可以在 Pypi 上找到它,而且速度非常快。

      【讨论】:

      • 这是一个非常好的排序数据的解决方案。我将其修改为即使在未排序的数据上也能工作,请参阅我复制函数的答案。
      猜你喜欢
      • 2018-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 2012-03-15
      • 2011-01-11
      相关资源
      最近更新 更多