乍一看,这个问题似乎非常基本且简单,但我在编写有效的解决方案时仍然遇到了一些困难。这个想法是编写一个函数,该函数将两个生成器作为输入并生成每个列表的一项。如果任一列表为空,它将生成剩余列表的每个项目。例子:
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 循环在另一个循环开始之前完成。这不是一个解决我的问题的问题,我而是在寻找一些代码来提高编写代码的技能!
一起使用zip_longest
和chain.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)
归档时间: |
|
查看次数: |
580 次 |
最近记录: |