以交替方式组合两个列表的 Pythonic 方式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3678869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:12:21  来源:igfitidea点击:

Pythonic way to combine two lists in an alternating fashion?

python

提问by davidchambers

I have two lists, the first of which is guaranteed to contain exactly one more item than the second. I would like to know the most Pythonic way to create a new list whose even-index values come from the first list and whose odd-index values come from the second list.

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

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

# desired output
['f', 'hello', 'o', 'world', 'o']

This works, but isn't pretty:

这有效,但并不漂亮:

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

How else can this be achieved? What's the most Pythonic approach?

这还能如何实现?最 Pythonic 的方法是什么?

采纳答案by Duncan

Here's one way to do it by slicing:

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

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

回答by David Z

There's a recipe for this in the itertoolsdocumentation:

itertools文档中有一个配方:

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))

回答by Mark Byers

This should do what you want:

这应该做你想做的:

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

回答by wheaties

I'd do the simple:

我会做简单的:

chain.from_iterable( izip( list1, list2 ) )

It'll come up with an iterator without creating any additional storage needs.

它将提供一个迭代器,而不会产生任何额外的存储需求。

回答by Tom Anderson

I'm too old to be down with list comprehensions, so:

我太老了,不能理解列表,所以:

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

回答by Jay

Here's a one liner that does it:

这是一个这样做的班轮:

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

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

回答by chernevik

Here's a one liner using list comprehensions, w/o other libraries:

这是一个使用列表推导式的单行代码,没有其他库:

list3 = [sub[i] for i in range(len(list2)) for sub in [list1, list2]] + [list1[-1]]

Here is another approach, if you allow alteration of your initial list1 by side effect:

这是另一种方法,如果您允许通过副作用更改初始 list1:

[list1.insert((i+1)*2-1, list2[i]) for i in range(len(list2))]

回答by Carlos Valiente

My take:

我的看法:

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

回答by jwp

Stops on the shortest:

在最短的时间停止:

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

Sure, resolving the next/__next__ method may be faster.

当然,解析 next/__next__ 方法可能会更快。

回答by killown

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