grouping a flat list of number by range

Jim Segrave jes at nl.demon.net
Thu Jun 1 18:11:21 EDT 2006


In article <1149196642.001466.53990 at c74g2000cwc.googlegroups.com>,
 <joh12005 at yahoo.fr> wrote:
>hello,
>
>i'm looking for a way to have a list of number grouped by consecutive
>interval, after a search, for example :
>
>[3, 6, 7, 8, 12, 13, 15]
>
>=>
>
>[[3, 4], [6,9], [12, 14], [15, 16]]
>
>(6, not following 3, so 3 => [3:4] ; 7, 8 following 6 so 6, 7, 8 =>
>[6:9], and so on)
>
>i was able to to it without generators/yield but i think it could be
>better with them, may be do you an idea?

There are probably better ways, but this works

>
>best regards,
>
>J.

class IterInterval(object):
    """Create an iterator which, given a list of integers,
    for each run of consecutive integers i...j, yields a two
    element list [i, j + 1]

    Singleton lists [i] return [i, i + 1]
    Empty lists return None
    """
    def __init__(self, seq):
        self.seq = seq
        self.firstval = None
        self.index = 0

    def __iter__(self):
        # firstval = the start of a run of consecutive integers
        # lastval = the last value found in the run
        # nextval = the most recent value taken from the input list
        if not self.firstval:
            # set up the first iteration
            if self.index >= len(self.seq):
                # empty list, return
                raise StopIteration
            self.firstval = lastval = int(self.seq[self.index])
            self.index += 1
        while True:
            if self.index >= len(self.seq):
                # list exhausted, output the last value read
                yield [self.firstval, lastval + 1]
                raise StopIteration
            nextval = int(self.seq[self.index])
            self.index += 1
            if nextval == lastval + 1:
                lastval = nextval
                continue
            else:
                # end of run - output the run, reset for next call
                yield [self.firstval, lastval + 1]
                self.firstval = lastval = nextval
                continue

if __name__ == '__main__':
    for l in [[3, 6, 7, 8, 12, 13, 15], [2], []]:
        print l, "=>", [lst for lst in  IterInterval(l)]

/usr/home/jes% python interval.py 
[3, 6, 7, 8, 12, 13, 15] => [[3, 4], [6, 9], [12, 14], [15, 16]]
[3] => [[3, 4]]
[] => []



-- 
Jim Segrave           (jes at jes-2.demon.nl)




More information about the Python-list mailing list