ActiveState Code

Recipe 496682: make ranges of contiguous numbers from a list of integers


This code makes ranges of contiguous numbers from a list of integers. Each range is 2-integers-tuple which is same as for builtin range() function's argument.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def list2range(lst):
    '''make iterator of ranges of contiguous numbers from a list of integers'''

    tmplst = lst[:]
    tmplst.sort()
    start = tmplst[0]

    currentrange = [start, start + 1]

    for item in tmplst[1:]:
        if currentrange[1] == item:
            # contiguous
            currentrange[1] += 1
        else:
            # new range start
            yield tuple(currentrange)
            currentrange = [item, item + 1]

    # last range
    yield tuple(currentrange)



if __name__ == '__main__':
    # test routine
    a = [1,2,3,4,5,6,7,8,10,11,12,23,24,25,26]
    b = [(1,9), (10,13), (23, 27)]
    c = list(list2range(a))

    if b != c:
        print 'failed!'
    else:
        print 'succeed!'
    print c

Comments

  1. 1. At 9 a.m. on 9 may 2006, Poor Yorick said:

    only works if list doesn't contain duplicate values. try weeding out duplicate values first:

    tmplst = list(set(tmplst)) tmplst.sort() start = tmplst[0] ...

  2. 2. At 12:38 p.m. on 9 may 2006, Raymond Hettinger said:

    Contrast with the example in the itertools docs. See http://www.python.org/doc/current/lib/itertools-example.html

    >>> data = [ 1,  4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
    >>> for k, g in groupby(enumerate(data), lambda (i,x):i-x):
           print map(operator.itemgetter(1), g)
    
    [1]
    [4, 5, 6]
    [10]
    [15, 16, 17, 18]
    [22]
    [25, 26, 27, 28]
    
  3. 3. At 3:07 p.m. on 9 may 2006, Kazuo Moriwaka (the author) said:

    duplicate values. Thank you for your comment! I forgot duplicate values.

Sign in to comment