itertools.izip brokeness
rurpy at yahoo.com
rurpy at yahoo.com
Fri Jan 6 02:13:13 EST 2006
"Michael Spencer" <mahs at telcopartners.com> wrote in message
news:mailman.107.1136516348.27775.python-list at python.org...
>
> > Bengt Richter wrote:
> ...
> >> >>> from itertools import repeat, chain, izip
> >> >>> it = iter(lambda z=izip(chain([3,5,8],repeat("Bye")), chain([11,22],repeat("Bye"))):z.next(), ("Bye","Bye"))
> >> >>> for t in it: print t
> >> ...
> >> (3, 11)
> >> (5, 22)
> >> (8, 'Bye')
> >>
> >> (Feel free to generalize ;-)
> >
>
> rurpy at yahoo.com wrote:
> > Is the above code as obvious as
> > izip([3,5,8],[11,22],sentinal='Bye')?
> > (where the sentinal keyword causes izip to iterate
> > to the longest argument.)
> >
>
> How about:
>
> from itertools import repeat
>
> def izip2(*iterables, **kw):
> """kw:fill. An element that will pad the shorter iterable"""
> fill = repeat(kw.get("fill"))
> iterables = map(iter, iterables)
> iters = range(len(iterables))
>
> for i in range(10):
> result = []
> for idx in iters:
> try:
> result.append(iterables[idx].next())
> except StopIteration:
> iterables[idx] = fill
> if iterables.count(fill) == len(iterables):
> raise
> result.append(fill.next())
> yield tuple(result)
>
> >>> list(izip2(range(5), range(3), range(8), range(2)))
> [(0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, None), (3, None, 3, None), (4, None, 4,
> None), (None, None, 5, None), (None, None, 6, None), (None, None, 7, None)]
> >>> list(izip2(range(5), range(3), range(8), range(2), fill="Empty"))
> [(0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, 'Empty'), (3, 'Empty', 3, 'Empty'), (4,
> 'Empty', 4, 'Empty'), ('Empty', 'Empty', 5, 'Empty'), ('Empty', 'Empty', 6,
> 'Empty'), ('Empty', 'Empty', 7, 'Empty')]
> >>>
This may be getting too kludgey but by counting the
exhausted iterators you can allow for arguments
containing infinite iterators:
def izip4(*iterables, **kw):
"""kw:fill. An element that will pad the shorter iterable
kw:infinite. Number of non-terminating iterators """
fill = repeat(kw.get("fill"))
iterables = map(iter, iterables)
iters = range(len(iterables))
finite_cnt = len(iterables) - kw.get("infinite", 0)
while True:
result = []
for idx in iters:
try:
result.append(iterables[idx].next())
except StopIteration:
iterables[idx] = fill
finite_cnt -= 1
if finite_cnt == 0:
raise
result.append(fill.next())
yield tuple(result)
>>> print list(izip4(range(5), range(3), range(8), range(2), fill='empty'))
[(0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, 'empty'), (3, 'empty', 3,
'empty'),
(4, 'empty', 4, 'empty'), ('empty', 'empty', 5, 'empty'),
('empty', 'empty', 6, 'empty'), ('empty', 'empty', 7, 'empty')]
>>> print list(izip4(range(5), repeat('foo'), range(8), count(), infinite=2, fill='empty'))
[(0, 'foo', 0, 0), (1, 'foo', 1, 1), (2, 'foo', 2, 2), (3, 'foo', 3,
3), (4, 'foo', 4, 4),
('empty', 'foo', 5, 5), ('empty', 'foo', 6, 6), ('empty', 'foo', 7, 7)]
More information about the Python-list
mailing list