【问题标题】:Pythonic way to create union of all values contained in multiple lists创建多个列表中包含的所有值的联合的 Pythonic 方法
【发布时间】:2010-01-28 00:44:41
【问题描述】:

我有一个列表列表:

lists = [[1,4,3,2,4], [4,5]]

我想展平此列表并删除所有重复项;或者,换句话说,应用集合联合操作:

desired_result = [1, 2, 3, 4, 5]

最简单的方法是什么?

【问题讨论】:

    标签: python list set-union


    【解决方案1】:

    set.union 做你想做的事:

    >>> results_list = [[1,2,3], [1,2,4]]
    >>> results_union = set().union(*results_list)
    >>> print(results_union)
    set([1, 2, 3, 4])
    

    您也可以对两个以上的列表进行此操作。

    【讨论】:

    • @sth,例如,谢谢,但是当我运行它时,我得到一个错误: Traceback(最近一次调用最后一次):文件“so_example.py”,第 33 行,在? results_union=set().union(*result_lists) TypeError: union() 只接受一个参数(给定 3 个)
    • @AJ:根据文档 (docs.python.org/library/stdtypes.html#set.union) union() 仅支持 Python 2.6 或更高版本的多个参数。您似乎使用了之前的版本,因此您可能必须使用显式循环:total = set(); for x in results_list: total.update(x) (s/;/\n/)
    • 您也可以通过将第二行更改为results_union = set.union(*(set(el) for el in results_list))来保存创建一个空集
    • @Jean-FrançoisFabre TypeError: descriptor 'union' requires a 'set' object but received a 'list' 至少在 python 3.6 中。
    • 如果您使用set.union(*results_list),您将手动绑定方法描述符,即将results_list 的第一个元素作为“self”发送。这产生了一些奇怪的限制:1. 没有正确地进行鸭式类型(现在第一个元素必须是集合子类的集合或实例),以及 2. 空 results_list 的联合将是一个错误(不正确的结果 -应该返回空集)。
    【解决方案2】:

    理解方式:

    [*{ j for i in lists for j in i }]
    

    [*functools.reduce(lambda x,y: {*x, *y}, lists)]
    

    【讨论】:

      【解决方案3】:

      因为您似乎使用的是 Python 2.5(顺便说一下,如果您需要 A 的版本!= 2.6,当前的生产版本,在您的 Q 中提及;-)并且想要一个列表而不是一个集合作为结果,我建议:

      import itertools
      
      ...
      
      return list(set(itertools.chain(*result_list)))
      

      itertools 通常是使用迭代器(以及多种序列或集合)的好方法,我衷心建议您熟悉它。尤其是itertools.chain,记录在here

      【讨论】:

      • +1 体验美妙的itertools 软件包的好时机。
      • @Alex 谢谢...编辑了我的问题以指定版本并免除我自己在版本中落后的责任:) 我会重点研究 itertools,感谢您的建议。
      • @AJ,不怪,毕竟我们都可能在这样的约束下受苦(但请记住在以后的 Qs 中指定!-);顺便说一下,itertools.chain 在 Python 2.4 中也可以正常工作。
      【解决方案4】:

      你也可以遵循这种风格

      In [12]: a = ['Orange and Banana', 'Orange Banana']
      In [13]: b = ['Grapes', 'Orange Banana']
      In [14]: c = ['Foobanana', 'Orange and Banana']
      
      In [20]: list(set(a) | set(b) | set(c))
      Out[20]: ['Orange and Banana', 'Foobanana', 'Orange Banana', 'Grapes']
      
      In [21]: list(set(a) & set(b) | set(c))
      Out[21]: ['Orange and Banana', 'Foobanana', 'Orange Banana']    
      

      【讨论】:

        【解决方案5】:

        列表不支持联合,列表是有序的,但集合支持。查看set.union

        【讨论】:

          【解决方案6】:
          desired_result = [x for y in lists for x in y]
          

          【讨论】:

            【解决方案7】:

            我用下面的做交叉点,这样就避免了集合的需要。

            a, b= [[1,2,3], [1,2]]
            s = filter( lambda x: x in b, a)
            

            或者,

            s = [ x for x in b if x in a ]
            

            【讨论】:

            • 你为什么还要“避免对集合的需求”?为此,它们更快、更清晰。每次执行时,您的“x in a”都会在列表中进行线性、蛮力搜索。糟糕。
            • sets 需要类型转换,除非你处理一个大的 N,否则线速度也不错。
            • “类型转换”?在 Python 中?从何时起?集合基本上是只有键的字典,它们使用哈希和相等比较。在列表中使用“x in a”也会进行相等比较。类型转换是怎么回事?
            猜你喜欢
            • 2019-03-20
            • 1970-01-01
            • 2015-10-14
            • 1970-01-01
            • 2020-02-28
            • 1970-01-01
            • 1970-01-01
            • 2016-02-26
            • 1970-01-01
            相关资源
            最近更新 更多