交替附加两个列表中的元素

Posted

技术标签:

【中文标题】交替附加两个列表中的元素【英文标题】:alternately appending elements from two lists 【发布时间】:2017-02-27 14:23:36 【问题描述】:

我有三个包含元素的列表:

a = [[0,1],[2,3],...]
b = [[5,6],[7,8],...]

c = []

我想将 ab 中的元素附加到 c 中以获得:

c = [ [0,1],[5,6],[2,3],[7,8],.... ]

【问题讨论】:

你的意思是[5,6]而不是[5,3] 如果列表不等长怎么办? 您要从列表ab中依次添加元素吗? 【参考方案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.chainzip

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】:

使用实现itertoolsroundrobin 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 个空格

以上是关于交替附加两个列表中的元素的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 将元素附加到领域中的列表不会保留元素

附加到 Python 中的列表:每次都添加最后一个元素?

我们又来了:将一个元素附加到 R 中的列表中

我们又来了:将一个元素附加到 R 中的列表中

如何在两个元素之间附加一个元素

如何将 Vuetify v-menu 附加到可滚动列表中的父元素?