【问题标题】:Python: Speed up matching in multiple listsPython:加速多个列表中的匹配
【发布时间】:2018-12-27 22:17:19
【问题描述】:

我有四个这样的列表:

L = [ (1,2), (3,5), (6,10), (7,8) ]
M = [ (1,3), (8,9), (12,13) ]
N = [ (6,10), (3,4), (5,6), (10,11), (12,13) ]
T = [ (6,10) , (1,4) ]

我想检查 L、M 和 N 中每个 T 元组的存在/不存在:

[[True, False, True], [False, False, False]]

以下方法有效,但当 T、L、M 和 N 的大小增加时,效率非常低。

[[ y in x for x in [L, M, N] ] for y in T ]

对于大型列表来说,加速这一过程的最有效方法是什么?

【问题讨论】:

    标签: python performance list tuples matching


    【解决方案1】:

    list 中的搜索时间与列表长度成正比。所以对于长列表来说它很高。有针对搜索优化的特殊数据结构。 python 中最简单的是set。它计算每个元素的散列(因此元素必须是可散列的,并且整数元组是可以的)。 然后你做同样的检查。所以你只需要添加

    L = set(L)
    M = set(M)
    N = set(N)
    

    作为副作用,您将丢失列表中元素的顺序。如果存在非唯一值,它们将合并为一个。

    关于加速的更新:

    如果搜索值位于最开始,则在 list 中的搜索时间可能会很长。但如果不是这种情况,set 应该会快得多,因为搜索时间与 log(len(data)) 成正比。 list 最坏的情况是list 中没有搜索到的项目,因此需要检查每个项目。在这种情况下,在 1M list 中搜索会比在 set 中慢 200K(刚刚在 python3 中检查)

    【讨论】:

    • ...这将提供 30% 的加速,而无需重大算法更改。
    • @ForceBru 对于涉及的大型集合/列表,这应该是一个更显着的改进。你从哪里得到这个号码?
    • @schwobaseggl,我也这么认为。 sets 太棒了!我刚刚在我的机器上测试了这个。
    • 我刚刚测试了 1M 值的列表,并且 set 比列表快了大约 100 倍
    【解决方案2】:

    您还可以考虑使用 Numpy 数组而不是普通的 Python 列表和元组。 看here 由于您必须检查列表中的每个元素,因此总速度将始终线性扩展,因此您必须使用更快的实现,如 numpy 或使用更快的语言(如 Rust、C、C++)扩展您的代码。

    使用np.asarray(listname)函数进行转换

    【讨论】:

      【解决方案3】:

      改为使用字典并比较这些值。

      LMNT = {'L':[(1,2),(3,5),(6,10),(7,8)],
      'M':[(1,3),(8,9),(12,13)],
      'N':[ (6,10), (3,4), (5,6), (10,11), (12,13) ],
      'T':[ (6,10) , (1,4) ]}
      

      然后你可以比较字典。 LMNT['M'][0][1] 值为 2

      LMNT['N'][4] 的值为(12,13)

      【讨论】:

      • 这将比 OP 的原始代码效率低。现在需要更长的时间,因为列表仍然是列表,但需要额外的字典查找成本。
      【解决方案4】:

      如果你可以处理不同的输出格式,你也可以设置交集。

      >>> L = set([ (1,2), (3,5), (6,10), (7,8) ])
      >>> M = set([ (1,3), (8,9), (12,13) ])
      >>> N = set([ (6,10), (3,4), (5,6), (10,11), (12,13) ])
      >>> T = set([ (6,10) , (1,4) ])
      >>> [T & x for x in (L,M,N)]
      [{(6, 10)}, set(), {(6, 10)}]
      

      这将为您提供一个出现在两个集合中的元组集合列表。这应该比使用嵌套循环更快。

      【讨论】:

        猜你喜欢
        • 2016-04-24
        • 2021-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-02
        • 1970-01-01
        相关资源
        最近更新 更多