以交替方式合并两个列表的Python方式?

以交替方式合并两个列表的Python方式?,python,Python,我有两个列表,第一个列表保证比第二个列表多包含一个项目。我想知道创建一个新列表的最python的方法,它的偶数索引值来自第一个列表,奇数索引值来自第二个列表 # example inputs list1 = ['f', 'o', 'o'] list2 = ['hello', 'world'] # desired output ['f', 'hello', 'o', 'world', 'o'] 这是可行的,但并不漂亮: list3 = [] while True: try:

我有两个列表,第一个列表保证比第二个列表多包含一个项目。我想知道创建一个新列表的最python的方法,它的偶数索引值来自第一个列表,奇数索引值来自第二个列表

# example inputs
list1 = ['f', 'o', 'o']
list2 = ['hello', 'world']

# desired output
['f', 'hello', 'o', 'world', 'o']
这是可行的,但并不漂亮:

list3 = []
while True:
    try:
        list3.append(list1.pop(0))
        list3.append(list2.pop(0))
    except IndexError:
        break

除此之外,如何实现这一目标?什么是最具python风格的方法?

下面是一个方法:

编辑: 对于大于3的python版本:

from itertools import cycle, islice

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).__next__ for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

在Python 2中,这应该满足您的要求:

>>> iters = [iter(list1), iter(list2)]
>>> print list(it.next() for it in itertools.cycle(iters))
['f', 'hello', 'o', 'world', 'o']

这里有一种通过切片实现的方法:

>>> list1 = ['f', 'o', 'o']
>>> list2 = ['hello', 'world']
>>> result = [None]*(len(list1)+len(list2))
>>> result[::2] = list1
>>> result[1::2] = list2
>>> result
['f', 'hello', 'o', 'world', 'o']
我会做简单的事情:

chain.from_iterable( izip( list1, list2 ) )

它将提供一个迭代器,而不需要创建任何额外的存储需求。

我太老了,无法理解列表,因此:

import operator
list3 = reduce(operator.add, zip(list1, list2))

这是一个单行程序:


list3=[item for pair in zip(list1,list2+[0])for item in pair][:-1]

这里有一个使用列表理解的单行程序,没有其他库:

list3 = [sub[i] for i in range(len(list2)) for sub in [list1, list2]] + [list1[-1]]
以下是另一种方法,如果您允许通过副作用更改初始列表1:

[list1.insert((i+1)*2-1, list2[i]) for i in range(len(list2))]
我的看法:

a = "hlowrd"
b = "el ol"

def func(xs, ys):
    ys = iter(ys)
    for x in xs:
        yield x
        yield ys.next()

print [x for x in func(a, b)]
在最短的路线上停车:

def interlace(*iters, next = next) -> collections.Iterable:
    """
    interlace(i1, i2, ..., in) -> (
        i1-0, i2-0, ..., in-0,
        i1-1, i2-1, ..., in-1,
        .
        .
        .
        i1-n, i2-n, ..., in-n,
    )
    """
    return map(next, cycle([iter(x) for x in iters]))
当然,解析next/uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def combine(list1, list2):
    lst = []
    len1 = len(list1)
    len2 = len(list2)

    for index in range( max(len1, len2) ):
        if index+1 <= len1:
            lst += [list1[index]]

        if index+1 <= len2:
            lst += [list2[index]]

    return lst
lst=[] len1=len(列表1) len2=len(列表2) 对于范围内的索引(最大值(len1,len2)):
如果索引+1没有itertools,并且假设l1比l2长1项:

>>> sum(zip(l1, l2+[0]), ())[:-1]
('f', 'hello', 'o', 'world', 'o')
在python 2中,使用itertools并假设列表不包含任何内容:

>>> filter(None, sum(itertools.izip_longest(l1, l2), ()))
('f', 'hello', 'o', 'world', 'o')

这是基于卡洛斯·瓦伦特的上述贡献 通过一个选项,可以交替多个项目组,并确保输出中存在所有项目:

A=["a","b","c","d"]
B=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]

def cyclemix(xs, ys, n=1):
    for p in range(0,int((len(ys)+len(xs))/n)):
        for g in range(0,min(len(ys),n)):
            yield ys[0]
            ys.append(ys.pop(0))
        for g in range(0,min(len(xs),n)):
            yield xs[0]
            xs.append(xs.pop(0))

print [x for x in cyclemix(A, B, 3)]
这将按每组3个值交错列出A和B:

['a', 'b', 'c', 1, 2, 3, 'd', 'a', 'b', 4, 5, 6, 'c', 'd', 'a', 7, 8, 9, 'b', 'c', 'd', 10, 11, 12, 'a', 'b', 'c', 13, 14, 15]

我知道这些问题是关于两个列表的,其中一个列表中的一项比另一项多,但我想我会把这个问题留给其他可能会发现这个问题的人

这里的内容适用于两个不同大小的列表

list1 = ['f', 'o', 'o', 'b', 'a', 'r']
list2 = ['hello', 'world']
num = min(len(list1), len(list2))
result = [None]*(num*2)
result[::2] = list1[:num]
result[1::2] = list2[:num]
result.extend(list1[num:])
result.extend(list2[num:])
result
这将产生:

['f', 'hello', 'o', 'world', 'o', 'b', 'a', 'r'] 

这很糟糕,但不管列表的大小,都会起作用:

list3 = [element for element in list(itertools.chain.from_iterable([val for val in itertools.izip_longest(list1, list2)])) if element != None]

我认为这是最具python风格的方法。

多行一行的灵感来自:


可能有点晚了再买一条python one班轮。当两个列表的大小相等或不相等时,此选项有效。一件毫无价值的事情是它会修改a和b。如果这是一个问题,您需要使用其他解决方案

a = ['f', 'o', 'o']
b = ['hello', 'world']
sum([[a.pop(0), b.pop(0)] for i in range(min(len(a), len(b)))],[])+a+b
['f', 'hello', 'o', 'world', 'o']

努比怎么样?它也适用于字符串:

import numpy as np

np.array([[a,b] for a,b in zip([1,2,3],[2,3,4,5,6])]).ravel()
结果:

array([1, 2, 2, 3, 3, 4])

一种功能性和不可变的替代方法(Python 3):


如果两个列表长度相等,则可以执行以下操作:

[x for y in zip(list1, list2) for x in y]
由于第一个列表还有一个元素,您可以在事后添加它:

[x for y in zip(list1, list2) for x in y] + [list1[-1]]

可能的重复不是重复!上面链接的文章中接受的答案产生了一个元组列表,而不是一个单一的合并列表。@Paul:是的,接受的答案没有给出完整的解决方案。阅读评论和其他答案。这个问题基本上是一样的,其他的解决方案也可以在这里应用。@Felix:我不同意。诚然,这些问题都在同一个社区,但实际上并不重复。作为模糊的证据,看看这里的潜在答案,并与其他问题进行比较。看看这些:它非常简单,但它只适用于相同长度的列表!您可以使用
chain来修复它。对于此处询问的特定问题,请从_iterable(izip(list1,list2),list1[len(list2):])
。。。列表1应该是较长的一个。是的,但我宁愿提出一个适用于任意长度容器的解决方案,或者屈服于上面提出的解决方案。我非常喜欢你最初的答案。虽然它并没有完美地解决这个问题,但合并两个相同长度的列表是一种优雅的方式。我建议在您当前的回答中保留它以及长度警告。如果列表1改为['f','o','o','d',],其最后一项('d')将不会出现在结果列表中(考虑到问题的具体情况,这完全可以)。这是一个优雅的解决方案@马克·耶普(我确实投了赞成票),只是指出了不同之处(如果其他人想要不同的行为,还有限制)+1来解决所陈述的问题,而且做得也很简单:-)我认为这样的事情是可能的。老实说,我认为这种情况下,
roundrobin
函数有点过分了。要处理任何大小的列表,只需将迭代器中剩余的内容附加到结果:
list(itertools.chain(map(next,itertools.cycle(iters)),*iters))
谢谢,邓肯。我没有意识到在切片时可以指定一个步骤。我喜欢这种方法的原因是它读起来很自然。1.列出正确的长度。2.用列表1的内容填充偶数索引。3.用列表2的内容填充奇数索引。在这种情况下,列表长度不同不是问题!我认为它只在len(list1)-len(list2)为0或1时有效。如果列表的长度合适,则它有效,如果长度不合适,则原始问题不会指定期望的答案。它可以很容易地修改,以处理最合理的情况:例如,如果您想忽略额外的元素,只需在开始之前砍掉较长的列表;如果您想让额外的元素与None交错,那么只需确保使用更多的None初始化结果;如果你想在末尾添加额外的元素,那么就忽略它们,然后附加它们。我也不清楚。我想指出的一点是,邓肯的解决方案与许多列出的解决方案不同,并没有因为列表长度不等而变得复杂。当然,它只适用于有限的情况,但我更喜欢在这种情况下工作的真正优雅的解决方案,而不是适用于任何两个列表的不那么优雅的解决方案。您可以使用(2*len(list1)-1)而不是(len(list1)+len(list2)),而且我更喜欢[0::2]而不是[::2]。这是正确的,但正如我所想的那样
array([1, 2, 2, 3, 3, 4])
from itertools import zip_longest
from functools import reduce

reduce(lambda lst, zipped: [*lst, *zipped] if zipped[1] != None else [*lst, zipped[0]], zip_longest(list1, list2),[])
from itertools import chain
list(chain(*zip('abc', 'def')))  # Note: this only works for lists of equal length
['a', 'd', 'b', 'e', 'c', 'f']
[x for y in zip(list1, list2) for x in y]
[x for y in zip(list1, list2) for x in y] + [list1[-1]]