python 多个列表_python中多个列表的串联

本问题已经有最佳答案,请猛点这里访问。

假设我有这样一个函数:

def getNeighbors(vertex)

返回与给定顶点相邻的顶点列表。现在我想创建一个列表,列出所有邻居的邻居。我是这样做的:

listOfNeighborsNeighbors = []

for neighborVertex in getNeighbors(vertex):

listOfNeighborsNeighbors.append(getNeighbors(neighborsVertex))

有没有比这更像Python的方法?

不过,我认为复制品和这个问题都选择了错误的答案。请参阅此处了解更多的Python式/表演式答案。

通常的解决方案,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]

因此,问题的解决办法是list(itertools.chain.from_iterable(getNeighbors(n) for n in getNeighbors(vertex)))。

appending列表可以完成与+和sum():

>>> c = [[1, 2], [3, 4]]

>>> sum(c, [])

[1, 2, 3, 4]

谢谢-我知道有办法用SUM来做这个!顺便说一句,我不清楚这是否适用于两个以上的子列表或可变长度列表;所以更清楚的例子可能是:c = [[1, 2], [3, 4, 5], [6, 7]]=>[1, 2, 3, 4, 5, 6, 7]。

但是看看我在EMU的回答下所做的评论。不要使用SUM——对于100个项目的100个列表来说非常慢!

为什么需要求和的第二个参数?我认为SUM([[1,2],[3,4]])是一天的意思是[1,2]+[3,4]。

[x for n in getNeighbors(vertex) for x in getNeighbors(n)]

sum(getNeighbors(n) for n in getNeighbors(vertex), [])

+我打算提出一个理解清单的建议。嗯,这是最刺激的方式。

但是,请参阅时间比较,作为emu答案下的注释:"itertools.chain"和"reduce(iadd)"的速度是嵌套列表理解速度的两倍以上,比sum()快得多,后者在处理了个元素后会迅速退化。

很高兴我找到这个。试了很多次,从来没有用这样的第二个论点来计算清单的总和。

如果速度的问题,它可能是更好的使用这个:

from operator import iadd

reduce(iadd, (getNeighbors(n) for n in getNeighbors(vertex)))

本代码是在该点的列表在列表list.extendconcatenating全由一对一个项目的理解会增加,如果list.append调用。saves位是架空的,制作前(根据我的测量约三倍)的速度。(通常是书面的+=iadd算子和不相同的东西的list.extend)。

使用列表(第一液)comprehensions Ignacio)仍然是正确的,它是通常的方式,更容易阅读。

但绝对避免使用sum(..., []),因为它运行在二次。这是非常impractical列表是很多(超过百或OS)。

感谢Re-Sum的评论——我喜欢代码的紧凑性,所以很高兴知道不要大规模使用它。imho,jochen's itertools'chain solution from'10是一个比reduce更合适的解决方案:它更直接/更简单地执行所要求的操作。

我收回我所说的关于链条更合适的说法。虽然我发现它更容易阅读/理解,但如果最终目标是创建一个列表,它会有一个轻微的性能问题:它一次传递一个元素,因此列表无法预测它将持续多长时间。从这个意义上讲,它更类似于列表理解/附加,而不是减少/扩展。使用timeit,对于100个列表x 100个元素,减少/iadd与链的时间大致相等(1.1)。有了4倍的数据(200个列出了x 200个元素),就可以减少获胜次数(2.6对4.0)。

警告:IADD修改传入的第一个列表。在示例中并不重要,因为列表是函数的结果。但我做了一个测试,在测试中我通过了一个预先计算的列表。修改了我原来的名单,这不好做。修正:代替reduce(iadd, LL)甚至reduce(iadd, (L for L in LL))必须将每个返回的l包装在list():reduce(iadd, (list(L) for L in LL))中。这将强制复制每个L。(因为尺寸已知,所以速度很快)。

…列表理解下降更快(2.4=>9.1)。总和更糟(13.8=>130.2)!把这些数字重复在一起以便比较:(减少,链接,理解,和)@100x100=(1.1,1.1,2.6,13.8);@200x200=(2.6,4.0,9.1,130.2)。

测试代码(python 2.7):print timeit('all = reduce(operator.iadd, (list(list_) for list_ in LL))', number=1000, setup='n = 100; import operator; L1 = list(range(n)); LL = [[10 * x + v for v in L1] for x in range(n)]')print timeit('all = list(itertools.chain(*LL))', number=1000, setup='n = 100; L1 = list(range(n)); LL = [[10 * x + v for v in L1] for x in range(n)]')print timeit('all = [x for list_ in LL for x in list_]', number=...print timeit('all = sum(LL, [])', number=...然后用n = 200;代替100重复这4个步骤。(然后我将结果乘以10)

@你知道为什么和在二次时间内运行吗?这让我吃惊。

@toolmakersteve您可以将第二个参数添加到reduce作为初始值,从而避免了复制列表的需要。

@因为它别无选择,只能在每次添加时构建一个新的列表,这是一个线性时间操作。

采用高速类:

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=[];

for l in list_of_lists:

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

itertools.chain(list_of_lists)是错误的(它不会连接任何东西,因为它只提供了一个参数)。你需要一个*,或者chain.from_iterable。

这些定时结果可能会过时。使用python3.6.6测试2018硬件,我看不到itertools.chain、itertools.chain.from iterable和functools.reduce/iadd解决方案之间有任何可复制的速度差异。YMMV。不过,IADD解决方案会更改输入。

我喜欢,因为它运行在itertools.chain方法(线性和二次(……)中的时间),但"约翰不展示如何处理的动态列表的长度。这里是一个解决方案是打开的。

import itertools

list(itertools.chain(*[getNeighbors(n) for n in getNeighbors(vertex)]))

你可以摆脱list(...)呼叫,如果你是足够的迭代变量。

您也可以通过这样使用chain.from_iterable:list(itertools.chain.from_iterable(getNeighbors(n) for n in getNeighbors(vertex))),来摆脱对*[getNeighbors...]的解包。

利用.extend(更新)(就地)结合而减少(新对象)和(每个小组)应更有效,但是我太懒,:)试验

mylist = [[1,2], [3,4], [5,6]]

reduce(lambda acc_l, sl: acc_l.extend(sl) or acc_l, mylist)

它确实更快,但正如亚里夫的答案所示,它不是最快的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值