如何解压缩迭代器?
How to unzip an iterator?
给定一个列表对 xys
,将其解压缩到两个列表中的 Python 习惯用法是:
xs, ys = zip(*xys)
如果 xys
是一个迭代器,我如何将它解压缩为两个迭代器,而不将所有内容都存储在内存中?
如果您想独立于另一个迭代器使用一个迭代器,则无法避免将内容拉入内存,因为其中一个迭代器会进行,而另一个不会(因此必须进行缓冲)。
这样的事情可以让你迭代 'left items' 和 'right items' 对:
import itertools
import operator
it1, it2 = itertools.tee(xys)
xs = map(operator.itemgetter(0), it1))
ys = map(operator.itemgetter(1), it2))
print(next(xs))
print(next(ys))
...但请记住,如果您只使用一个迭代器,另一个将在内存中缓冲项目,直到您开始使用它们。
(顺便说一句,假设 Python 3。在 Python 2 中你需要使用 itertools.imap()
,而不是 map()
。)
假设你有一些可迭代的对:
a = zip(range(10), range(10))
如果我正确解释了您的要求,您可以使用 itertools.tee
:
为第一个和第二个生成独立的迭代器
xs, ys = itertools.tee(a)
xs, ys = (x[0] for x in xs), (y[1] for y in ys)
注意 这将在内存中保留 "difference" 你迭代其中一个与另一个之间的次数。
完整答案定位here. Long story short: we can modify Python recipe for itertools.tee
function喜欢
from collections import deque
def unzip(iterable):
"""
Transposes given iterable of finite iterables.
"""
iterator = iter(iterable)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
然后使用它
>>> from itertools import count
>>> zipped = zip(count(), count())
>>> xs, ys = unzip(zipped)
>>> next(xs)
0
给定一个列表对 xys
,将其解压缩到两个列表中的 Python 习惯用法是:
xs, ys = zip(*xys)
如果 xys
是一个迭代器,我如何将它解压缩为两个迭代器,而不将所有内容都存储在内存中?
如果您想独立于另一个迭代器使用一个迭代器,则无法避免将内容拉入内存,因为其中一个迭代器会进行,而另一个不会(因此必须进行缓冲)。
这样的事情可以让你迭代 'left items' 和 'right items' 对:
import itertools
import operator
it1, it2 = itertools.tee(xys)
xs = map(operator.itemgetter(0), it1))
ys = map(operator.itemgetter(1), it2))
print(next(xs))
print(next(ys))
...但请记住,如果您只使用一个迭代器,另一个将在内存中缓冲项目,直到您开始使用它们。
(顺便说一句,假设 Python 3。在 Python 2 中你需要使用 itertools.imap()
,而不是 map()
。)
假设你有一些可迭代的对:
a = zip(range(10), range(10))
如果我正确解释了您的要求,您可以使用 itertools.tee
:
xs, ys = itertools.tee(a)
xs, ys = (x[0] for x in xs), (y[1] for y in ys)
注意 这将在内存中保留 "difference" 你迭代其中一个与另一个之间的次数。
完整答案定位here. Long story short: we can modify Python recipe for itertools.tee
function喜欢
from collections import deque
def unzip(iterable):
"""
Transposes given iterable of finite iterables.
"""
iterator = iter(iterable)
try:
first_elements = next(iterator)
except StopIteration:
return ()
queues = [deque([element])
for element in first_elements]
def coordinate(queue):
while True:
if not queue:
try:
elements = next(iterator)
except StopIteration:
return
for sub_queue, element in zip(queues, elements):
sub_queue.append(element)
yield queue.popleft()
return tuple(map(coordinate, queues))
然后使用它
>>> from itertools import count
>>> zipped = zip(count(), count())
>>> xs, ys = unzip(zipped)
>>> next(xs)
0