交替附加两个列表中的元素
Posted
技术标签:
【中文标题】交替附加两个列表中的元素【英文标题】:alternately appending elements from two lists 【发布时间】:2017-02-27 14:23:36 【问题描述】:我有三个包含元素的列表:
a = [[0,1],[2,3],...]
b = [[5,6],[7,8],...]
c = []
我想将 a 和 b 中的元素附加到 c 中以获得:
c = [ [0,1],[5,6],[2,3],[7,8],.... ]
【问题讨论】:
你的意思是[5,6]
而不是[5,3]
?
如果列表不等长怎么办?
您要从列表a
和b
中依次添加元素吗?
【参考方案1】:
基本方法:
>>> a = [[0,1],[2,3]]
>>> b = [[5,6],[7,8]]
>>> c = []
>>> for pair in zip(a,b):
... c.extend(pair)
...
>>> c
[[0, 1], [5, 6], [2, 3], [7, 8]]
>>>
如果长度不相等,则会中断。但是您可以将这种情况作为练习来处理。
【讨论】:
【参考方案2】:使用字符串切片(和最高效)的另一种非常简单的方法:
>>> a = [[0,1],[2,3]]
>>> b = [[5,6],[7,8]]
>>> c = a + b # create a list with size = len(a) + len(b)
>>> c[::2], c[1::2] = a, b # alternately insert the value
>>> c
[[0, 1], [5, 6], [2, 3], [7, 8]]
下面是这里提到的答案与timeit
的结果对比(Python版本:2.7):
使用 字符串切片:每个循环 0.586 微秒
moin@moin-pc:~$ python -m "timeit" -s "a = [[0,1],[2,3]]; b = [[5,6],[7,8]];" "c = a + b; c[::2], c[1::2] = a, b"
1000000 loops, best of 3: 0.586 usec per loop
使用itertools.chain()
:每个循环1.89 微秒
moin@moin-pc:~$ python -m "timeit" -s "from itertools import chain; a = [[0,1],[2,3]]; b = [[5,6],[7,8]];" "c = list(chain(*zip(a, b)))"
1000000 loops, best of 3: 1.89 usec per loop
使用reduce()
:每个循环 0.829 微秒
moin@moin-pc:~$ python -m "timeit" -s "import operator; a = [[0,1],[2,3]]; b = [[5,6],[7,8]];" "c = reduce(operator.concat, zip(a, b))"
1000000 loops, best of 3: 0.829 usec per loop
使用 list.extend()
:每个循环 0.824 微秒
moin@moin-pc:~$ python -m "timeit" -s "a = [[0,1],[2,3]]; b = [[5,6],[7,8]]; c=[]" "for pair in zip(a,b): c.extend(pair)"
1000000 loops, best of 3: 0.824 usec per loop
使用list.append()
两次:每次循环 1.04 微秒
moin@moin-pc:~$ python -m "timeit" -s "a = [[0,1],[2,3]]; b = [[5,6],[7,8]]; c=[]" "for a_element, b_element in zip(a, b): c.append(a_element); c.append(b_element)"
1000000 loops, best of 3: 1.04 usec per loop
【讨论】:
好的。但是您确实应该使用-s
选项传递timeit
那些设置语句。 FWIW,在 Python 3.6 中,我的 [*chain(*zip(a, b))]
比我的 list(chain...)
version 快大约 10%,而我的 list comp 比这稍快。
@PM2Ring:是的,你是对的。我错过了。更新了答案。
@PM2Ring:我正在使用Python 2.7
,因此无法根据您提到的语法对其进行评估。但我在回答中已经提到我的评价是针对Python 2.7
【参考方案3】:
您可以zip
这两个列表,然后将它们简化为一个平面列表:
import operator
c = reduce(operator.concat, zip(a, b))
【讨论】:
【参考方案4】:假设两个列表的长度相同,最简洁的方法是使用itertools.chain
和zip
。
from itertools import chain
a = [[0,1],[2,3],[10,11],[12,13]]
b = [[5,6],[7,8],[15,16],[17,18]]
c = [*chain(*zip(a, b))]
print(c)
输出
[[0, 1], [5, 6], [2, 3], [7, 8], [10, 11], [15, 16], [12, 13], [17, 18]]
正如 juanpa.arrivillaga 在 cmets 中提到的那样,该语法不适用于旧版本的 Python。相反,您可以这样做
c = list(chain(*zip(a, b)))
这是另一个选项,它不使用导入或*
splat 运算符:
c = [u for t in zip(a, b) for u in t]
如果您需要处理长度不等的输入列表,请查看Itertools Recipes 中的roundrobin
函数。例如,
c = list(roundrobin(a, b))
【讨论】:
我想你的意思是list(chain(*zip(a,b)))
虽然我有点希望支持语法。
@juanpa.arrivillaga 我发布的代码适用于 Python 3.6。但我想我最好将旧语法添加到我的答案中。
哦!我应该开始许下更多的愿望!
@juanpa.arrivillaga:Python 3.6 很有趣。我还没有探索所有内容,但是格式字符串(又名 f 字符串)非常容易上瘾。 :)【参考方案5】:
考虑:
merged = []
for a_element, b_element in zip(a, b):
merged.append(a_element)
merged.append(b_element)
除非您有非常严格的性能要求,否则最简单的方法就是正确的方法。
【讨论】:
【参考方案6】:使用实现itertools
roundrobin
recipe的more_itertools
>>> from more_itertools import roundrobin
>>> a = [[0,1],[2,3]]
>>> b = [[5,6],[7,8]]
>>> list(roundrobin(a, b))
[[0, 1], [5, 6], [2, 3], [7, 8]]
【讨论】:
【参考方案7】:假设 len(a) == len(b) 并且您正在依次添加它们:
for i in range(len(a)):
c.append(a[i])
c.append(b[i])
但是,我建议使用c = deque()
。因为如果您进行大量追加,则双端队列会更快。
【讨论】:
选择您的代码并按 CTRL+K 以正确格式化。 从智能手机发布代码更复杂。 哦,好吧,我猜你只是在每一行缩进了 4 个空格以上是关于交替附加两个列表中的元素的主要内容,如果未能解决你的问题,请参考以下文章