@@ -445,3 +445,45 @@ def __next__(self):
445445 self ._iter = iter ([])
446446 raise StopIteration ()
447447 return value
448+
449+ class groupby (object ):
450+ """Make an iterator that returns consecutive keys and groups from the
451+ iterable. The key is a function computing a key value for each
452+ element. If not specified or is None, key defaults to an identity
453+ function and returns the element unchanged. Generally, the
454+ iterable needs to already be sorted on the same key function.
455+
456+ The returned group is itself an iterator that shares the
457+ underlying iterable with groupby(). Because the source is shared,
458+ when the groupby object is advanced, the previous group is no
459+ longer visible. So, if that data is needed later, it should be
460+ stored as a list:
461+
462+ groups = []
463+ uniquekeys = []
464+ for k, g in groupby(data, keyfunc):
465+ groups.append(list(g)) # Store group iterator as a list
466+ uniquekeys.append(k)
467+ """
468+ def __init__ (self , iterable , key = None ):
469+ if key is None :
470+ key = lambda x : x
471+ self ._keyfunc = key
472+ self ._iter = iter (iterable )
473+ self ._tgtkey = self ._currkey = self ._currvalue = xrange (0 )
474+
475+ def __iter__ (self ):
476+ return self
477+
478+ def __next__ (self ):
479+ while self ._currkey == self ._tgtkey :
480+ self ._currvalue = next (self ._iter ) # Exit on StopIteration
481+ self ._currkey = self ._keyfunc (self ._currvalue )
482+ self ._tgtkey = self ._currkey
483+ return (self ._currkey , self ._grouper (self ._tgtkey ))
484+
485+ def _grouper (self , tgtkey ):
486+ while self ._currkey == tgtkey :
487+ yield self ._currvalue
488+ self ._currvalue = next (self ._iter ) # Exit on StopIteration
489+ self ._currkey = self ._keyfunc (self ._currvalue )
0 commit comments