Python 在iterables中产生替代值

Python 在iterables中产生替代值,python,python-3.x,Python,Python 3.x,我得到了许多iterable,我需要生成第一个iterable中的所有值,然后是第二个iterable中的所有值,最后一个iterable中的所有值都是可选的 示例: for i in alternate('abcde','fg','hijk'): print(i,end=' ') 预计它将产生这些值 a f h b g i c 我知道按顺序打印所有字符,如 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' 代码如下: def

我得到了许多iterable,我需要生成第一个iterable中的所有值,然后是第二个iterable中的所有值,最后一个iterable中的所有值都是可选的

示例

for i in alternate('abcde','fg','hijk'): 
      print(i,end=' ')
预计它将产生这些值

a f h b g i c
我知道按顺序打印所有字符,如

'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'
代码如下:

def alternate(*args):
    for iterable in args:
        for item in iterable:
            yield item

但是,我该如何生成它们呢?

如果您想在最短列表中终止,请使用:

制作一个迭代器,聚合来自每个ITerable的元素

如果要使用所有项目,请使用:

制作一个迭代器,聚合来自每个ITerable的元素。如果iterables的长度不均匀,则缺少的值将用fillvalue填充

请注意,它跳过
None
值(可以使用
fillvalue
进行更改)

不带
itertools

def alternate(*args):
    max_len = max(map(len, args))
    for index in range(max_len):
        for lst in args:
            try:
                yield lst[index]
            except IndexError:
                continue
要在第一个“缺失”项上停止:

如果您正在使用生成器(或迭代器),当其中一个生成器(或迭代器)完成时,您将得到
StopIteration
,因此您可以使用
iter
创建一个通用函数:

def alternate(*args):
    iters = [iter(lst) for lst in args]
    while True:
        for itr in iters:
            try:
                yield next(itr)
            except StopIteration:
                return

这会满足你的要求。它适用于任何输入,如果其中一项为
None
,则不会出错。它使用内置的
itertools
模块,并且只使用内置的python模块在Python3.x和Python2.7上工作。它基于Python
itertools
文档中的函数:

from itertools import cycle

def roundrobin_shortest(*iterables):
    "roundrobin_shortest('ABCD', 'EF', 'GHI') --> A E G B F H C"
    nexts = cycle(iter(it).__next__ for it in iterables)
    while True:
        try:
            for inext in nexts:
                yield inext()
        except StopIteration:
            break
此版本的工作原理基本相同,但略短:

from itertools import chain, cycle

def roundrobin_shortest(*iterables):
    "roundrobin_shortest('ABCD', 'EF', 'GHI') --> A E G B F H C"
    nexts = cycle(iter(it).__next__ for it in iterables)
    yield from chain.from_iterable(inext() for inext in nexts)
和一个没有itertools的版本:

def roundrobin_shortest(*iterables):
    "roundrobin_shortest('ABCD', 'EF', 'GHI') --> A E G B F H C"
    items = [iter(item) for item in iterables]
    while True:
       try:
           for it in items:
               yield next(it)
       except StopIteration:
           break
您可以像这样使用其中任何一个:

>>> for i in roundrobin_shortest('abcde','fg','hijk'): 
...     print(i, end=' ')
...
a f h b g i c 
或者这里有一个更简单的一行

>>> from itertools import chain, cycle
>>> iters = ('abcde','fg','hijk')
>>> res = chain.from_iterable(j() for j in cycle(iter(j).__next__ for j in iters))
>>> print(' '.join(res))
a f h b g i c

什么python版本?@ReutSharabani python 3.
alternate('a','bcdefg','hijkl')
的预期输出是什么?有没有办法不使用izip_longest(*args)?@Hacker688
itertools
自Python 2.3以来一直在标准库中。@Hacker688这个问题通过文档链接以及在Python解释器中的一个非常简单的检查(需要5秒钟)得到了回答。@Hacker688 izip_longest在Python 3中被重命名。在python2中,zip_创建的是列表,而不是迭代器。回答中修正了:@Reut Sharabani,但输出是[a f h b g i c j d k e],而不是[a f h b g i c]
def roundrobin_shortest(*iterables):
    "roundrobin_shortest('ABCD', 'EF', 'GHI') --> A E G B F H C"
    items = [iter(item) for item in iterables]
    while True:
       try:
           for it in items:
               yield next(it)
       except StopIteration:
           break
>>> for i in roundrobin_shortest('abcde','fg','hijk'): 
...     print(i, end=' ')
...
a f h b g i c 
>>> from itertools import chain, cycle
>>> iters = ('abcde','fg','hijk')
>>> res = chain.from_iterable(j() for j in cycle(iter(j).__next__ for j in iters))
>>> print(' '.join(res))
a f h b g i c