Parsing numeric ranges

Seldon seldon at katamail.it
Thu Mar 3 10:25:00 EST 2011


On 02/25/2011 10:27 AM, Seldon wrote:
> Hi all,
> I have to convert integer ranges expressed in a popular "compact"
> notation (e.g. 2, 5-7, 20-22, 41) to a the actual set of numbers (i.e.
> 2,5,7,20,21,22,41).
>
> Is there any library for doing such kind of things or I have to write it
> from scratch ?
>

In addition to the solutions given by others (thanks!), just for 
reference I paste below what I have written to solve my little problem: 
  comments are welcome !

-------------------

# Define exceptions
class MalformedRangeListError(Exception): pass # raised if a string is\ 
not a valid numeric range list


def num_range_list_to_num_set(range_list, sep=','):
     """
     Convert a numeric list of ranges to the set of numbers it represents.

     @argument
     range_list: a numeric list of ranges, as a string of values 
separated by `sep` (e.g. '1, 3-5, 7')

     @argument:
     sep: a string used as a separator in `range_list` (e.g. ',', ' ')

     @return: the set represented by `range_list` (i.e. (1,3,4,5,7)).

     """

     # if given an empty range list, the function should return the\ 
empty set
     if range_list == '': return set()

     import re
     int_or_range = r'^([1-9]\d*)(?:-([1-9]\d*))?$' # match a single 
decimal number or a range of decimal numbers
     r = re.compile(int_or_range)

     # split the input string in a list of numbers and numeric ranges
     l = range_list.split(sep)
     result = set()
     for s in l:
         # check if the current string is a number or a valid numeric range
         m = r.match(s)
         if not m:
             raise MalformedRangeListError, "Input string is not a valid 
numeric range-list"
         matches = len(filter(lambda x:x, m.groups())) # how many 
regexp\ groups matched
         first = m.group(1)
         if matches == 2: # it's a range
             if m.group(1) > m.group(2):
                 raise MalformedRangeListError, "Input string is not a\ 
valid numeric range-list"
             last = m.group(2)
             result.update(range(int(first), int(last)+1)) # current\ 
item is a range, so add the full numeric range to the result set
         elif matches == 1: # it's a number
             result.add(int(first)) # current item is a number, so just\ 
add it to the result set
         else:
             raise MalformedRangeListError, "Input string is not a valid 
numeric range-list"
     return result



More information about the Python-list mailing list