生成两个列表的交替值的生成器函数

F.V*_*.V. 0 python generator

乍一看,这个问题似乎非常基本且简单,但我在编写有效的解决方案时仍然遇到了一些困难。这个想法是编写一个函数,该函数将两个生成器作为输入并生成每个列表的一项。如果任一列表为空,它将生成剩余列表的每个项目。例子:

 list(alternate("abcdefg", [1, 2, 3, 4])) == ["a", 1, "b",2, "c", 3, "d", 4, "e", "f", "g"]
Run Code Online (Sandbox Code Playgroud)

什么样的工作,但看起来很丑:

def alternate(xs1, xs2):
    xs1 = iter(xs1)
    xs2 = iter(xs2)
    while xs1 and xs2:
        try:
            yield next(xs1), next(xs2)
        except StopIteration:
                for x1 in xs1:
                    yield x1
                for x2 in xs2:
                    yield x2
Run Code Online (Sandbox Code Playgroud)

特别是我想避免在一开始就将输入转换为迭代器。我尝试使用 2 个简单的 for 循环,但这显然只返回每个列表的最后一个值,因为一个 for 循环在另一个循环开始之前完成。这不是一个解决我的问题的问题,我而是在寻找一些代码来提高编写代码的技能!

che*_*ner 5

一起使用zip_longestchain.from_iterable

>>> from itertools import chain, zip_longest
>>> [ x for x in chain.from_iterable(zip_longest("abcdefg", [1,2,3,4])) if x is not None]
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 'f', 'g']
Run Code Online (Sandbox Code Playgroud)

对于更明确且与您已有的类似的内容,请next单独处理每个调用,并立即跳出循环以迭代每个迭代器的其余部分。用于itertools.cycle在两个迭代器之间交替,直到其中一个迭代器耗尽。

from itertools import cycle

def alternate(xs1, xs2):
    xs1 = iter(xs1)
    xs2 = iter(xs2)
    for itr in cycle([xs1, xs2]):
        try:
            yield next(itr)
        except StopIteration:
            break

    yield from xs1
    yield from xs2
Run Code Online (Sandbox Code Playgroud)