Would like some thoughts on a grouped iterator.

breamoreboy at gmail.com breamoreboy at gmail.com
Mon Sep 5 05:59:11 EDT 2016


On Monday, September 5, 2016 at 10:42:27 AM UTC+1, Peter Otten wrote:
> Antoon Pardon wrote:
> 
> > I need an interator that takes an already existing iterator and
> > divides it into subiterators of items belonging together.
> > 
> > For instance take the following class, wich would check whether
> > the argument is greater or equal to the previous argument.
> > 
> > class upchecker:
> >     def __init__(self):
> > self.prev = None
> >     def __call__(self, arg):
> > if self.last is None:
> >             self.prev = arg
> >             return True
> >         elif arg >= self.last:
> >             self.prev = arg
> >             return True
> >         else:
> >             self.prev = arg
> > return False
> > 
> > So the iterator I need --- I call it grouped --- in combination with
> > the above class would be used someting like:
> > 
> > for itr in grouped([8, 10, 13, 11, 2, 17, 5, 12, 7, 14, 4, 6, 15, 16, 19,
> > 9, 0, 1, 3, 18], upchecker()):
> >     print list(itr)
> > 
> > and the result would be:
> > 
> > [8, 10, 13]
> > [11]
> > [2, 17]
> > [5, 12]
> > [7, 14]
> > [4, 6, 15, 16, 19]
> > [9]
> > [0, 1, 3, 18]
> > 
> > Anyone an idea how I best tackle this?
> 
> I always start thinking "There must be an elegant way to do this" and then 
> end with a clumsy wrapper around itertools.groupby().
> 
> $ cat grouped.py
> from itertools import groupby
> 
> 
> class Check:
>     def __init__(self, check):
>         self.first = True
>         self.prev = None
>         self.toggle = False
>         self.check = check
> 
>     def __call__(self, item):
>         if self.first:
>             self.first = False
>         else:
>             if not self.check(self.prev, item):
>                 self.toggle = not self.toggle
>         self.prev = item
>         return self.toggle
> 
> 
> def grouped(items, check):
>     return (g for k, g in groupby(items, Check(check)))
> 
> 
> if __name__ == "__main__":
>     def upchecker(a, b):
>         return a < b
> 
>     items = [
>         8, 10, 13, 11, 2, 17, 5, 12, 7, 14, 4, 6, 15, 16, 19, 9, 0, 1, 3, 18
>     ]
>     for itr in grouped(items, upchecker):
>         print(list(itr))
> 
> $ python grouped.py
> [8, 10, 13]
> [11]
> [2, 17]
> [5, 12]
> [7, 14]
> [4, 6, 15, 16, 19]
> [9]
> [0, 1, 3, 18]

As usual you beat me to it, but I'd spell "upchecker" as "from operator import lt" :)



More information about the Python-list mailing list