以交替方式结合两个列表的Pythonic方法是什么?

135 投票
26 回答
123987 浏览
提问于 2025-04-16 03:55

我有两个列表,第一个列表的元素比第二个多一个。我想知道用最“Pythonic”的方式创建一个新列表,这个新列表的偶数索引位置的值来自第一个列表,而奇数索引位置的值来自第二个列表。

# 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

还有什么其他方法可以做到这一点?最“Pythonic”的方式是什么?


如果你需要处理长度不匹配的列表(比如第二个列表更长,或者第一个列表比第二个多出多个元素),这里的一些解决方案可以用,而其他的可能需要调整。想要更具体的答案,可以查看 如何交错两个不同长度的列表?,以便把多余的元素放在最后,或者 如何优雅地交错两个不等长的列表?,尝试均匀地插入元素,或者 在Python列表中每隔n个元素插入一个元素,适用于需要在每个“添加”的元素前放置特定数量元素的情况。

相关问题:

26 个回答

55
import itertools

print(
    [x for x in itertools.chain.from_iterable(itertools.zip_longest(list1, list2)) if x]
)

我觉得这是最符合Python风格的做法。

56

在这个itertools 文档里,有一个相关的例子(注意:这是针对Python 3的):

from itertools import cycle, islice

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

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

>>> 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']

撰写回答