【问题标题】:Python -Intersection of multiple lists?Python - 多个列表的交集?
【发布时间】:2011-04-20 15:33:06
【问题描述】:

我正在玩 python,并且能够得到两个列表的交集:

result = set(a).intersection(b)

现在如果d 是一个包含ab 以及第三个元素c 的列表,那么是否有一个内置函数可以在d 中查找所有三个列表的交集?比如,

d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]

那么结果应该是

[3,4]

【问题讨论】:

    标签: python list set intersection


    【解决方案1】:

    我发现reduce() 特别有用。其实numpy文档推荐使用reduce()来交叉多个列表:numpy.intersect1d reference

    回答你的问题:

    import numpy as np
    from functools import reduce
    # apply intersect1d to (a list of) multiple lists:
    reduce(np.intersect1d, [list_1, list_2, ... list_n])
    

    【讨论】:

      【解决方案2】:

      对于 2.4,你可以只定义一个交集函数。

      def intersect(*d):
          sets = iter(map(set, d))
          result = sets.next()
          for s in sets:
              result = result.intersection(s)
          return result
      

      对于较新版本的python:

      intersection 方法接受任意数量的参数

      result = set(d[0]).intersection(*d[1:])
      

      或者,您可以将第一个集合与自身相交以避免分割列表并制作副本:

      result = set(d[0]).intersection(*d)
      

      我不太确定哪个会更有效,并且感觉它取决于 d[0] 的大小和列表的大小,除非 python 有类似的内置检查

      if s1 is s2:
          return s1
      

      在交集法中。

      >>> d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]
      >>> set(d[0]).intersection(*d)
      set([3, 4])
      >>> set(d[0]).intersection(*d[1:])
      set([3, 4])
      >>> 
      

      【讨论】:

      • @AaronMcSmooth:如果我这样做,它会给我AttributeError: 'list' object has no attribute 'intersection'。我错过了什么吗?
      • @Legend。您必须先将其映射到一组。我不知何故错过了它们是列表的事实。之后,您可以将列表(或任何其他可迭代的)传递给 intersection 方法
      • @AaronMcSmooth:实际上,不知道为什么,但无论我尝试什么解决方案,我都会收到此错误:TypeError: intersection() takes exactly one argument (3 given)
      • @Legend。我的回答和 TokenMacGuy 在 python 2.6 和 3.1 上为我所做的工作
      • @Legend。感谢您清理我的帖子。但请记住:'主这样说:“你要缩进四个空格。不多也不少。你要缩进的空格数是四,你的缩进数是四。你不能缩进八,也不要缩进你两个,除非你继续到四个。制表符是魔鬼的苹果!”'
      【解决方案3】:

      您可以使用set.intersection(set1, set2, set3...) 获得任意数集的交集。因此,您只需要将列表转换为集合,然后将它们传递给此方法,如下所示:

      d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]  
      set.intersection(*[set(x) for x in d])  
      

      结果:

      {3, 4}
      

      【讨论】:

        【解决方案4】:

        Lambda 减少。

        from functools import reduce #you won't need this in Python 2
        l=[[1, 2, 3, 4], [2, 3, 4], [3, 4, 5, 6, 7]]
        reduce(set.intersection, [set(l_) for l_ in l])
        

        【讨论】:

        • 你需要一个 set 列表,如果说'descriptor intersection requires set'会失败
        【解决方案5】:

        @user3917838

        很好很简单,但需要一些强制转换才能使其工作并作为结果给出一个列表。它应该看起来像:

        list(reduce(set.intersection, [set(item) for item in d ]))

        地点:

        d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]

        结果是:

        [3, 4]

        至少在 Python 3.4 中

        【讨论】:

          【解决方案6】:
          set.intersection(*map(set,d))
          

          【讨论】:

          • 不确定这里出了什么问题。现在它给了我:TypeError: intersection() takes exactly one argument (2 given)
          • 非常感谢。为此+1。由于我的 Python 版本,我无法使用它:(
          • 如果d 变量的长度可能为零,则set.intersection 函数将引发TypeError 异常。我建议捕获该异常并在该退化情况下返回set()(一个空集)。这比事先检查dlen 要好,因为它可能是一个生成器。
          • @AaronR:好点,但集合交集的退化解是全集,而不是空集。因为在 python 中没有紧凑的方式来表示它,所以引发异常(可能捕获类型错误并引发更明智的事情)仍然可能是处理它的正确方法。然而,返回一个空集集合并集的正确做法。
          • @TokenMacGuy:是的,你说的很对;与en.wikipedia.org/wiki/Empty_product 类比,它将是唯一能保证不会改变交集结果的集合。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多