【问题标题】:Python list intersection efficiency: generator or filter()?Python列表交集效率:生成器还是过滤器()?
【发布时间】:2019-11-17 12:22:45
【问题描述】:

我想在 Python (2.7) 中将两个列表相交。我需要结果是可迭代的:

list1 = [1,2,3,4]
list2 = [3,4,5,6]
result = (3,4) # any kind of iterable

提供一个完整的迭代会在交集之后首先执行,以下哪个更有效?

使用生成器:

result = (x for x in list1 if x in list2)

使用过滤器():

result = filter(lambda x: x in list2, list1)

其他建议?

提前致谢,
暗嫩

【问题讨论】:

    标签: python list intersection python-2.7 intersect


    【解决方案1】:

    这些都不是。最好的方法是使用集合。

    list1 = [1,2,3,4]
    list2 = [3,4,5,6]
    result = set(list1).intersection(list2)
    

    集合是可迭代的,所以不需要将结果转换成任何东西。

    【讨论】:

    • 有趣,set(list1).intersection(list2) 比 set(list1) & set(list2) 快,我想这是因为创建两个集合比加载和调用 .intersection() 更昂贵..
    • @mouad 在我的机器上,set(list1) & set(list2) 比使用.intersection() 更快。但差别不是很大。
    • 这是否需要对列表进行排序?
    • @Youda008 列表不需要排序。集合是通过散列实现的,因此无论在原始列表中的位置如何,查找都会在平均 O(1) 时间内发生。
    【解决方案2】:

    您的解决方案的复杂度为O(m*n),其中m 和n 是两个列表的各自长度。您可以将复杂性提高到O(m+n),使用其中一个列表的集合:

    s = set(list1)
    result = [x for x in list2 if x in s]
    

    如果速度比可读性更重要(即几乎从不),您也可以使用

    result = filter(set(a).__contains__, b)
    

    这比我机器上的其他解决方案快约 20%。

    【讨论】:

      【解决方案3】:

      我尝试比较了列表交集的3种方法的速度:

      import random
      
      a = [random.randint(0, 1000) for _ in range(1000)]
      b = [random.randint(0, 1000) for _ in range(1000)]
      

      解决方案 1:列表理解

      时间流逝:8.95265507698059

      import time
      start = time.time()
      for _ in range(1000):
          result = [x for x in a if x in b]
      elapse = time.time() - start
      print(elapse) 
      

      解决方案 2:设置

      经过时间:0.09089064598083496

      start = time.time()
      for _ in range(1000):
          result = set.intersection(set(a), set(b))
      elapse = time.time() - start
      print(elapse) 
      

      解决方案 3:numpy.intersect1d

      经过时间:0.323300838470459

      start = time.time()
      for _ in range(1000):
          result = np.intersect1d(a, b)
      elapse = time.time() - start
      print(elapse) 
      

      结论

      我认为使用set.intersection 是最快的方式。

      【讨论】:

        【解决方案4】:

        对于列表的情况,最有效的方法是使用:

        result = set(list1).intersection(list2)
        

        如前所述,但对于 numpy 数组,intersection1d 函数更有效:

        import numpy as np
        result = np.intersection1d(list1, list2)
        

        特别是,当您知道列表没有重复值时,您可以将其用作:

        result = np.intersection1d(list1, list2, assume_unique=True)
        

        【讨论】:

          猜你喜欢
          • 2020-12-25
          • 2016-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多