加入python中的列表列表

Koz*_*huk 284 python

在python中将列表列表加入单个列表(或迭代器)的简短语法是什么?

例如,我有一个如下列表,我想迭代a,b和c.

x = [["a","b"], ["c"]]
Run Code Online (Sandbox Code Playgroud)

我能想到的最好的是如下.

result = []
[ result.extend(el) for el in x] 

for el in result:
  print el
Run Code Online (Sandbox Code Playgroud)

CTT*_*CTT 424

import itertools
a = [['a','b'], ['c']]
print(list(itertools.chain.from_iterable(a)))
Run Code Online (Sandbox Code Playgroud)

  • 稍微好一点:`list(itertools.chain.from_iterable(a))` (95认同)
  • result = []; map(result.extend,a)比itertools.chain快约30%.但是chain.from_iterable比map + extend快一点.[Python 2.7,x86_64] (46认同)
  • 一点解释也不错.http://docs.python.org/library/itertools.html#itertools.chain (10认同)
  • 无需列出()它!对于itertools.chain中的项目(*a):使用item做一些事情 (8认同)
  • 这解释了`*a`发生了什么:http://stackoverflow.com/questions/5239856/foggy-on-asterisk-in-python(它将`a`的元素作为参数发送到`chain`,比如删除外部`[`和`]`). (4认同)
  • 如果您有许多可迭代对象要连接,则 chain.from_iterable 会明显更快。对我来说,从 100 个 Python 列表(每个列表包含 10 个或 100 个顶点)创建 OpenGL 顶点的 ctypes 数组时,速度要快 50%。“*”运算符将可迭代对象转换为传递到链中的中间元组。 (2认同)
  • 如果某些元素只是字符串,则此方法不起作用:[["aaa", "bbb"], "ccc"] 给出 ["aaa", "bbb", "c", "c", "c"]。 (2认同)

Geo*_*lly 169

如果你只是深入一级,嵌套的理解也会起作用:

>>> x = [["a","b"], ["c"]]
>>> [inner
...     for outer in x
...         for inner in outer]
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

在一行,这成为:

>>> [j for i in x for j in i]
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

  • Listception .. 这绝对是非 Python 式的 / 与 Python 的禅宗背道而驰,因为它不是最简单或最明确的方法。您最终会进行硬编码递归。不过还是很酷。 (3认同)
  • 非常酷,所以对于下一个深度级别,它将变成 [i for ll in x for l in ll for i in l] - 在这一点上它开始对读者来说有点蹩脚,但仍然很酷:) (2认同)
  • @ZachEstela,我很高兴看到有人称之为untythonic.似乎许多其他人喜欢称为pythonic的技术乍一看并不容易理解.可读性是使Python对我有吸引力的因素之一.这个解决方案很酷,可能是最快的,但`sum(x,[])`解决方案更像是Pythonic. (2认同)
  • 那些“更pythonic”的答案是错误的。问题不是关于递归加入,而是加入列表列表,这意味着没有更多的深度级别要加入。 (2认同)

CMS*_*CMS 147

x = [["a","b"], ["c"]]

result = sum(x, [])
Run Code Online (Sandbox Code Playgroud)

  • 这里的O(n ^ 2)基本上意味着该函数执行所需的时间与输入长度的平方成正比.因此,如果您将输入加倍,则需要的时间翻两番.如果您有大量输入,这是一件坏事,但对于小型输入,它应该没问题.但更快的方法会更好. (12认同)
  • 非常优雅! (6认同)
  • 读起来多么糟糕啊!我使用 python 的次数越多,它的半完成状态就越能击中要害。我无法想象为什么标准库没有内置 flat() 函数。 (5认同)
  • 最简单,最聪明的解决方案。 (4认同)
  • @Julian:你错了.只是时间,或参见http://stackoverflow.com/a/952952/279627. (3认同)
  • @Requin `sum(iterable, start)` 将 `iterable` 中的所有元素添加到 `start` 中。添加列表会将它们连接起来。`start` 默认为 0,如果 `interable` 由列表组成,则会中断,因为您无法将列表添加到 int,因此我们传递一个空列表作为开始。 (3认同)
  • @Aaron,请教一个noob python学习者:在这种情况下,O(n ^ 2)是好还是坏?;-) (2认同)
  • @ACK_stoverflow文档说使用`chain`来组合可迭代对象,而不是列表。如果只需要可迭代的结果,则可以这样做,并避免额外的复制。如果结果仍然需要列表,我怀疑`chain`会更好。 (2认同)
  • 有人可以解释“sum(x, [])”如何以及为什么起作用吗? (2认同)

Pao*_*ino 29

这被称为展平,并且有很多实现:

这个怎么样,虽然它只适用于1级深度嵌套:

>>> x = [["a","b"], ["c"]]
>>> for el in sum(x, []):
...     print el
...
a
b
c
Run Code Online (Sandbox Code Playgroud)

从这些链接,显然最完整,快速优雅等实现如下:

def flatten(l, ltypes=(list, tuple)):
    ltype = type(l)
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        i += 1
    return ltype(l)
Run Code Online (Sandbox Code Playgroud)

  • 你的"最完美 - 优雅 - 等"根本不是"优雅"!看看itertools.chain的文档,看看真正的优雅! (5认同)
  • 啊,'sum(L,I)'是'reduce(plus_operator,L,I)'的简写.那有点酷. (4认同)
  • @hasen j:我相信他对任意嵌套列表来说意味着最好.链假设一个一致的,一个深的列表列表(这可能是所有问题的需要),但扁平处理像[a,b,[c],[d,[e,f]],[[[g] ]]]. (4认同)

nat*_*e c 27

l = []
map(l.extend, list_of_lists)
Run Code Online (Sandbox Code Playgroud)

最短!

  • sum(listoflists,[])#short! (13认同)
  • 在 Python 3.1+ 中,用 `list()` 包裹 `map`,否则你会在打印结果时看到 `&lt;map object at 0x0000...&gt;` (7认同)
  • @recursive较短但功能不同=表现更差,请参阅其他变体的评论以获得解释 (4认同)

Geo*_*lly 15

这对于无限嵌套元素递归工作:

def iterFlatten(root):
    if isinstance(root, (list, tuple)):
        for element in root:
            for e in iterFlatten(element):
                yield e
    else:
        yield root
Run Code Online (Sandbox Code Playgroud)

结果:

>>> b = [["a", ("b", "c")], "d"]
>>> list(iterFlatten(b))
['a', 'b', 'c', 'd']

  • @Darthfett你会期望一个有意义的结果来展平"无限嵌套列表"吗?:-) (2认同)

Evg*_*eev 11

性能比较:

import itertools
import timeit
big_list = [[0]*1000 for i in range(1000)]
timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
Run Code Online (Sandbox Code Playgroud)

生产:

>>> import itertools
>>> import timeit
>>> big_list = [[0]*1000 for i in range(1000)]
>>> timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
[3.016212113769325, 3.0148865239060227, 3.0126415732791028]
>>> timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
[3.019953987082083, 3.528754223385439, 3.02181439266457]
>>> timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
[1.812084445152557, 1.7702404451095965, 1.7722977998725362]
>>> timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[5.409658160700605, 5.477502077679354, 5.444318360412744]
>>> [100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
[399.27587954973444, 400.9240571138051, 403.7521153804846]
Run Code Online (Sandbox Code Playgroud)

这是在Windows XP 32位上的Python 2.7.1,但上面的评论中的@temoto from_iterable必须更快map+extend,因此它非常依赖于平台和输入.

保持距离 sum(big_list, [])

  • 有一些反对票。我无法弄清楚他们指的是什么。如果您发现错误,您能指出来吗?如果出现错误,应该很容易修复,这对后代游客来说是件好事。 (3认同)

Mic*_*ett 6

迟到了,但......

我是python的新手,来自lisp背景.这就是我提出的(查看lulz的var名称):

def flatten(lst):
    if lst:
        car,*cdr=lst
        if isinstance(car,(list,tuple)):
            if cdr: return flatten(car) + flatten(cdr)
            return flatten(car)
        if cdr: return [car] + flatten(cdr)
        return [car]
Run Code Online (Sandbox Code Playgroud)

似乎工作.测试:

flatten((1,2,3,(4,5,6,(7,8,(((1,2)))))))
Run Code Online (Sandbox Code Playgroud)

收益:

[1, 2, 3, 4, 5, 6, 7, 8, 1, 2]
Run Code Online (Sandbox Code Playgroud)

  • 你来自lisp背景?我从来没有想过代码......哈哈 (15认同)

Jer*_*ten 5

您所描述的内容被称为展列表,利用这些新知识,您将能够在Google上找到许多解决方案(没有内置的展平方法).以下是其中之一,来自http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/:

def flatten(x):
    flat = True
    ans = []
    for i in x:
        if ( i.__class__ is list):
            ans = flatten(i)
        else:
            ans.append(i)
    return ans
Run Code Online (Sandbox Code Playgroud)


cul*_*rón 5

如果需要列表而不是生成器,请使用 list():

from itertools import chain
x = [["a","b"], ["c"]]
y = list(chain(*x))
Run Code Online (Sandbox Code Playgroud)