【问题标题】:How do I flatten a list of lists/nested lists? [duplicate]如何展平列表/嵌套列表的列表? [复制]
【发布时间】:2013-12-05 10:32:45
【问题描述】:

我有这样的python代码:

newlist =[[52, None, None], [129, None, None], [56, None, None], [111, None, None],  
          [22, None, None], [33, None, None], [28, None, None], [52, None, None],  
          [52, None, None], [52, None, None], [129, None, None], [56, None, None],  
          [111, None, None], [22, None, None], [33, None, None], [28, None, None]]

我想要newlist 喜欢:

newlist =[52, None, None,129, None, None,56, None, None,111, None, None,22, 
          None, None,33, None, None,28, None, None,52, None, None,52, None,  
          None,52, None, None,129, None, None,56, None, None, 111, None,  
          None,22, None, None,33, None, None,28, None, None]

有什么办法可以解决吗?

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    您正在尝试做的事情称为展平列表。根据Zen of Python,您正在尝试做正确的事情。引用自那

    平面比嵌套好。

    1. 所以你可以像这样使用列表推导

      newlist = [item for items in newlist for item in items]
      
    2. 或者你可以像这样使用itertools中的chain

      from itertools import chain
      newlist = list(chain(*newlist))
      
    3. 或者你可以使用chain.from_iterable,这里不需要解包列表

      from itertools import chain
      newlist = list(chain.from_iterable(newlist))
      
    4. 使用sum函数

      newlist = sum(newlist, [])
      
    5. 使用reduce函数

      newlist = reduce(lambda x,y: x+y, newlist)
      
    6. 使用operator.add。这将比带有lambda 版本的reduce 更快。

      import operator
      newlist = reduce(operator.add, newlist)
      

    编辑:为了完整起见,也包括在Making a flat list out of list of lists in Python 中找到的答案。

    我尝试在 Python 2.7 中对所有这些进行计时,就像这样

    from timeit import timeit
    print(timeit("[item for items in newlist for item in items]", "from __main__ import newlist"))
    print(timeit("sum(newlist, [])", "from __main__ import newlist"))
    print(timeit("reduce(lambda x,y: x+y, newlist)", "from __main__ import newlist"))
    print(timeit("reduce(add, newlist)", "from __main__ import newlist; from operator import add"))
    print(timeit("list(chain(*newlist))", "from __main__ import newlist; from itertools import chain"))
    print(timeit("list(chain.from_iterable(newlist))", "from __main__ import newlist; from itertools import chain"))
    

    在我的机器上输出

    2.26074504852
    2.45047688484
    3.50180387497
    2.56596302986
    1.78825688362
    1.61612296104
    

    因此,最有效的方法是在 Python 2.7 中使用 list(chain.from_iterable(newlist))。在 Python 3.3

    中运行相同的测试
    from timeit import timeit
    print(timeit("[item for items in newlist for item in items]", "from __main__ import newlist"))
    print(timeit("sum(newlist, [])", "from __main__ import newlist"))
    print(timeit("reduce(lambda x,y: x+y, newlist)", "from __main__ import newlist; from functools import reduce"))
    print(timeit("reduce(add, newlist)", "from __main__ import newlist; from operator import add; from functools import reduce"))
    print(timeit("list(chain(*newlist))", "from __main__ import newlist; from itertools import chain"))
    print(timeit("list(chain.from_iterable(newlist))", "from __main__ import newlist; from itertools import chain"))
    

    在我的机器上输出

    2.26074504852
    2.45047688484
    3.50180387497
    2.56596302986
    1.78825688362
    1.61612296104
    

    所以,无论是 Python 2.7 还是 3.3,都可以使用 list(chain.from_iterable(newlist)) 来展平嵌套列表。

    【讨论】:

    • 有一个问题。为什么[i for j in l for i in j] 有效而[i for i in j for j in l] 无效?
    • @tMJ 在第二种形式中,再次理解子列表,而不是子列表中的单个元素。在这两种情况下,只需打破理解并打印i 的值即可。
    • @tMJ:考虑等效的 for 循环。第一个是for j in l: for i in j: newlist.append(i),第二个是for i in j: for j in l: newlist.append(i)
    • @tMJ:在 Python 2 中,列表解析会泄漏循环变量。再试一次,但del j介于两者之间,你会看到NameError: name 'j' is not defined
    • 一个非常详细的答案,我在一段时间内看到的最好的。 +1
    【解决方案2】:

    只是最简单的一个:

    newlist = sum(newlist, [])
    print newlist
    

    【讨论】:

      【解决方案3】:

      试试:

      newlist = [j for i in newlist for j in i]
      

      【讨论】:

        【解决方案4】:
        temp = []
        for small_list in newlist:
            temp += small_list
        newlist = temp
        

        应该这样做。

        【讨论】:

        • 这是二次的吗?使用 temp.extend(small_list) 可能会更好。
        • 二次方是什么意思?
        • stackoverflow.com/questions/3653298/… 使用+= 比使用.extend() 稍微好一点
        • 二次表示 O(n^2) 时间。
        猜你喜欢
        • 2018-07-04
        • 1970-01-01
        • 1970-01-01
        • 2015-04-13
        • 1970-01-01
        • 2012-03-09
        • 1970-01-01
        • 2012-11-18
        • 2013-11-13
        相关资源
        最近更新 更多