兩個項目我已經定義了一個發生器,產生從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