Python中许多列表的连接

Bjö*_*lex 33 python list concatenation

假设我有这样的函数:

def getNeighbors(vertex)
Run Code Online (Sandbox Code Playgroud)

它返回一个顶点列表,这些顶点是给定顶点的邻居.现在我想创建一个包含邻居所有邻居的列表.我这样做:

listOfNeighborsNeighbors = []
for neighborVertex in getNeighbors(vertex):
    listOfNeighborsNeighbors.append(getNeighbors(neighborsVertex))
Run Code Online (Sandbox Code Playgroud)

是否有更多的pythonic方式来做到这一点?

小智 52

像往常一样,itertools模块包含一个解决方案:

>>> l1=[1, 2, 3]

>>> l2=[4, 5, 6]

>>> l3=[7, 8, 9]

>>> import itertools

>>> list(itertools.chain(l1, l2, l3))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

  • 如果 `ls = [l1,l2,l3]` 使用 `list(itertools.chain(*ls))`。 (3认同)
  • 因此,问题的解决方案是`list(itertools.chain.from_iterable(getNeighbors(n)for getNeighbors(vertex)中的n))。 (2认同)

Ign*_*ams 35

[x for n in getNeighbors(vertex) for x in getNeighbors(n)]
Run Code Online (Sandbox Code Playgroud)

要么

sum(getNeighbors(n) for n in getNeighbors(vertex), [])
Run Code Online (Sandbox Code Playgroud)

  • 但是,请参阅时序比较,作为emu答案下的评论:"itertools.chain"和"reduce(iadd")的速度是嵌套列表理解的两倍 - 并且比sum()快得多,后者随着速度迅速降低处理了#个元素. (5认同)
  • 第二个解决方案看起来很酷。并在实践中发挥作用。这花费了我数小时的分析和调试时间,因为它不适用于大 N!请注意,第二个解决方案的时间复杂度是二次方! (2认同)

Sjo*_*erd 33

附加列表可以使用+和sum()完成:

>>> c = [[1, 2], [3, 4]]
>>> sum(c, [])
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

  • 但是看到我在鸸's的答案下做的评论时间.**不要使用SUM - 非常慢**为100个100项目列表! (7认同)

emu*_*emu 12

如果速度很重要,最好使用它:

from operator import iadd
reduce(iadd, (getNeighbors(n) for n in getNeighbors(vertex)))
Run Code Online (Sandbox Code Playgroud)

这段代码的重点是连接整个列表list.extend,列表理解将逐个添加一个项目,就像调用一样list.append.这节省了一些开销,使前者(根据我的测量)大约快三倍.(iadd操作员通常被写为+=和做同样的事情list.extend.)

使用列表推导(Ignacio的第一个解决方案)通常仍然是正确的方式,它更容易阅读.

但绝对避免使用sum(..., []),因为它以二次方运行.对于许多列表(超过一百个左右)来说,这是非常不切实际的.


Yar*_*riv 11

按速度排序:

list_of_lists = [[x,1] for x in xrange(1000)]

%timeit list(itertools.chain(*list_of_lists))
100000 loops, best of 3: 14.6 µs per loop

%timeit list(itertools.chain.from_iterable(list_of_lists))
10000 loops, best of 3: 60.2 µs per loop

min(timeit.repeat("ll=[];\nfor l in list_of_lists:\n ll.extend(l)", "list_of_lists=[[x,1] for x in xrange(1000)]",repeat=3, number=100))/100.0
9.620904922485351e-05

%timeit [y for z in list_of_lists for y in z]
10000 loops, best of 3: 108 µs per loop

%timeit sum(list_of_lists, [])
100 loops, best of 3: 3.7 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • 这些时间结果可能已经过时.使用python3.6.6在2018 HW上进行测试,我没有看到itertools.chain,itertools.chain.from_iterable和functools.reduce/iadd解决方案之间存在任何可重现的速度差异.因人而异.但是,iadd解决方案会改变输入. (3认同)