两个项目我已经定义了一个发生器,产生从Elasticsearch日志条目:遍历发生器同时
def gen():
....
for hit in results:
yield hit
我怎么能遍历两个元素在同一时间?东西的线路:
for one, two in gen():
...
通过两个元素我的意思是这样的:A, B
,B, C
,...,Y, Z
(为A, B, ..., Y, Z
生成的列表)。
两个项目我已经定义了一个发生器,产生从Elasticsearch日志条目:遍历发生器同时
def gen():
....
for hit in results:
yield hit
我怎么能遍历两个元素在同一时间?东西的线路:
for one, two in gen():
...
通过两个元素我的意思是这样的:A, B
,B, C
,...,Y, Z
(为A, B, ..., Y, Z
生成的列表)。
回答您的问题更新,使用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')
谢谢。这是最干净,最“pythonic”的方式吗?我觉得这个简单问题的解决方案很复杂。
我不认为有一个更清洁的解决方案。事实上,它是从itertools docs的pairwise
配方:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
这个答案假设你想要非重叠对。因为迭代器消耗您可以通过zip()
做到这一点:
for one, two in zip(gen, gen):
# do something
例子:
>>> gen = (x for x in range(5))
>>> for one, two in zip(gen, gen): print(one,two)
...
0 1
2 3
注意,如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
我一旦解决了类似的问题,以下内容:
def gen():
results = [1, 2, 3, 4, 5]
for i, v in enumerate(results):
# if i < len()
if (i + 1) < len(results):
yield (v, results[i + 1])
else:
yield v
output = gen()
for each in output:
print(each)
输出将是:
(1, 2)
(2, 3)
(3, 4)
(4, 5)
5
由于生成器循环遍历分页的Elasticsearch结果,因此我认为将所有内容加载到内存中并不是最佳选择,以便将项目逐个分组。 – linkyndy
谢谢。这是最干净,最“pythonic”的方式吗?我觉得这个简单问题的解决方案很复杂。 – linkyndy
感谢您指出itertools配方! – linkyndy
@AndreiHorak没有问题,如果你使用的是Python 2,请确保使用'izip',特别是如果你的迭代器/生成器可以产生无限量的对象。 – timgeb