seansummers
10/20/2015 - 7:46 PM

``````from itertools import tee, izip

def range_to_group(lst):
"""generate string integer sets from a list of integers

>>> tuple(range_to_group([-3,2,5,6,-4]))
('-4--3', '2', '5-6')
"""

a, b = tee(sorted(set(lst)))
next(b, None)
i = izip(a, b)
for x, y in i:
start = stop = x
while y - x == 1:
stop = y
x, y = next(i, (0, 0))
yield ("{}" if start == stop else "{}-{}").format(start, stop)

def range_extract(lst):
"""create string integer sets from list

>>> range_extract([4,5,7,8,-6,-3,-2,3,4,5,9,10,20])
'-6,-3--2,3-5,7-10'
>>> range_extract([1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14])
'1-6,8-12'
"""

return ",".join(range_to_group(lst))

if __name__ == "__main__":
import doctest
doctest.testmod()
``````
``````from itertools import chain

def group_to_range(group):
"""parse single string integer set to list

Handles arbitrary whitespace, out-of-order
and negative integers.

>>> group_to_range("-3--1")
[-3, -2, -1]
>>> group_to_range("3-2")
[2, 3]
>>> group_to_range(" 3 -  - 2 ")
[-2, -1, 0, 1, 2, 3]
"""

group = "".join(group.split())
sign, g = ("-", group[1:]) if group.startswith("-") else ("", group)
r = g.split("-", 1)
r[0] = "".join((sign, r[0]))
r = sorted(int(__) for __ in r)
return range(r[0], 1 + r[-1])

def range_expand(txt):
"""parse string of integer sets with intervals to list

Handles arbitrary whitespace, overlapping ranges, out-of-order ranges,
and negative integers.

>>> range_expand("-6,-3--1,3-5,7-11,14,15,17-20")
[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
>>> range_expand("1-4,6,3-2, 11, 8 - 12,5,14-14")
[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14]
"""

ranges = chain.from_iterable(group_to_range(__) for __ in txt.split(","))
return sorted(set(ranges))

if __name__ == "__main__":
import doctest
doctest.testmod()
``````
``````from pyparsing import Literal, nums, Word, Optional, Combine, delimitedList, Suppress

def parse_integer(s, l, t):
return int(t[0])

def parse_integer_range(s, l, t):
x, y = t[0], t[-1]
x, y = min(x, y), max(x, y) + 1
return range(x, y)

def parse_integer_range_list(s, l, t):
return sorted(set(t))

sign = Literal('+') | Literal('-')
number = Word(nums)

integer = Combine(Optional(sign) + number, adjacent=False)
integer.setParseAction(parse_integer)

integer_range = integer + Suppress('-') + integer
integer_range.setParseAction(parse_integer_range)

integer_range_list = delimitedList(integer_range | integer, ',')
integer_range_list.setParseAction(parse_integer_range_list)

if __name__ == '__main__':
print integer_range_list.parseString("1-4,6,3-2, 11, 8 - 12,5,14-14")
``````