So splitting a list using itertools.groupby()
is a fairly easy.
>>> import itertools as it
>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2)
>>> for x, y in iterable:
... print(x, list(y))
... next(iterable)
False [1]
False [3, 4, 5]
False [3, 4]
Works as expected. But using a common python idiom of zip
ing up the iterator multiple times to step through 2 at a time seems to break things.
>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2)
>>> for (x, y), _ in zip(iterable, iterable):
... print(x, list(y))
False []
False []
False []
Adding a print(y)
shows the expected nested iterable <itertools._grouper object at 0xXXXXXXXX>
, but I'm obviously missing something as to why the grouper
object is empty. Can anyone shed some light?
I get an even weirder result if I have an uneven list and use itertools.zip_longest
:
>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4], lambda p: p==2)
>>> for (x, y), _ in it.zip_longest(iterable, iterable, fillvalue=None):
... print(x, list(y))
False []
False []
False [4]
Update: Simple fix is to use itertools.islice()
:
>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2)
>>> for x, y in it.islice(iterable, None, None, 2):
... print(x, list(y))
False [1]
False [3, 4, 5]
False [3, 4]
The
groupby
documentation warns you thatWhen your
zip
produces a((key, group), (key, group))
pair, it advances thegroupby
iterator past the first group, rendering the first group unusable. You need to materialize the group before advancing: