一次循环生成两个项目

lin*_*ndy 6 python generator

我已经定义了一个生成Elasticsearch的日志条目的生成器:

def gen():
    ....
    for hit in results:
        yield hit
Run Code Online (Sandbox Code Playgroud)

如何同时循环两个元素?有些东西:

for one, two in gen():
    ...
Run Code Online (Sandbox Code Playgroud)

由两个元素我的意思是:A, B,B, C,..., Y, Z(对于一个生成的列表A, B, ..., Y, Z).

Chr*_*nds 8

这个答案假设你想要不重叠的对.您可以通过zip()因为迭代器被消耗来执行此操作:

for one, two in zip(gen, gen):
    # do something
Run Code Online (Sandbox Code Playgroud)

例:

>>> gen = (x for x in range(5))
>>> for one, two in zip(gen, gen): print(one,two)
... 
0 1
2 3
Run Code Online (Sandbox Code Playgroud)

请注意,正如timgeb所评论的那样,itertools.zip_longest如果元素数量不均匀,并且您希望最后一个元素具有填充值,则应该使用,例如:

>>> gen = (x for x in range(5))
>>> for one, two in zip_longest(gen, gen): print(one, two)
... 
0 1
2 3
4 None
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果从生成器中产生的对象数量不均匀,则不会产生最后一个元素.在这种情况下,使用`itertools.izip_longest`将获得`(last_element,None)`(或您想要的任何填充值). (2认同)

tim*_*geb 6

回答你的更新问题,用于itertools.tee构造第二个迭代器,推进第二个迭代器一次并丢弃结果,然后使用成对循环两个迭代器zip.

>>> from itertools import tee
>>> it = iter('abc')
>>> it1, it2 = tee(it)
>>> 
>>> next(it2, None)
'a'
>>> for first, second in zip(it1, it2):
...     first, second
... 
('a', 'b')
('b', 'c')
Run Code Online (Sandbox Code Playgroud)

谢谢.这是最干净,最"pythonic"的方式吗?我觉得这个简单问题的解决方案是复杂的.

我认为没有更清洁的解决方案.事实上,它是pairwise来自itertools文档的配方:

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)
Run Code Online (Sandbox Code Playgroud)