@@ -445,3 +445,45 @@ def __next__(self):
445
445
self ._iter = iter ([])
446
446
raise StopIteration ()
447
447
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