Expand the range that looks like this: "1-3,6,8-10" - [1,2,3, 6, 8,9,10]

I am trying to add a parameter to my program that allows the user to choose which program steps he wants to take.

I would like to be able to parse a string like "1-3,6,8-10" and get [1, 2, 3, 6, 8, 9, 10] .

Do you know that something in Python that does this already exists?

+4
python
source share
7 answers

This function does what you requested. He assumes that negative numbers are not used, otherwise some changes are needed to support this case.

 def mixrange(s): r = [] for i in s.split(','): if '-' not in i: r.append(int(i)) else: l,h = map(int, i.split('-')) r+= range(l,h+1) return r print mixrange('1-3,6,8-10') 
+8
source share

One way to use lists is:

 s = "1-3,6,8-10" x = [ss.split('-') for ss in s.split(',')] x = [range(int(i[0]),int(i[1])+1) if len(i) == 2 else i for i in x] print [int(item) for sublist in x for item in sublist] 

Outputs:

 [1, 2, 3, 6, 8, 9, 10] 
+3
source share

There is no built-in function as such, but it can be used with xrange and generators:

 from itertools import chain s = "1-3,6,8-10" spans = (el.partition('-')[::2] for el in s.split(',')) ranges = (xrange(int(s), int(e) + 1 if e else int(s) + 1) for s, e in spans) all_nums = chain.from_iterable(ranges) # loop over, or materialse using `list` # [1, 2, 3, 6, 8, 9, 10] 
+2
source share

A small function that I just created:

 def expand(st): res = [] for item in st.split(','): if '-' in item: temp = map(int, item.split('-')) res.extend(range(temp[0], temp[1]+1)) else: res.append(int(item)) return res s = '1-3,6,8-10' print expand(s) 

Return:

 [1, 2, 3, 6, 8, 9, 10] 
+1
source share
 def parseIntSet(nputstr=""): selection = set() invalid = set() # tokens are comma seperated values tokens = [x.strip() for x in nputstr.split(',')] for i in tokens: try: # typically tokens are plain old integers selection.add(int(i)) except: # if not, then it might be a range try: token = [int(k.strip()) for k in i.split('-')] if len(token) > 1: token.sort() # we have items seperated by a dash # try to build a valid range first = token[0] last = token[len(token)-1] for x in range(first, last+1): selection.add(x) except: # not an int and not a range... invalid.add(i) # Report invalid tokens before returning valid selection print "Invalid set: " + str(invalid) return selection 

Via: Parsing a list of numbers in Python

0
source share
 s = '1-3,6,8-10,13-16' temp = [x.split('-') if '-' in x else x for x in s.split(',')] # temp = [['1', '3'], '6', ['8', '10'], ['13', '16']] res = [] for l in temp: if isinstance(l, list): a, b = map(int, l) res = res + range(a, b + 1) else: res.append(int(l)) # res = [1, 2, 3, 6, 8, 9, 10, 13, 14, 15, 16] 
0
source share

Yeah, a one-line proof of someone's concept?

EDIT: Enhanced Version

 import itertools s = "1-3,6,8-10" print(list(itertools.chain.from_iterable(range(int(ranges[0]), int(ranges[1])+1) for ranges in ((el+[el[0]])[:2] for el in (miniRange.split('-') for miniRange in s.split(',')))))) 

Now divide into several lines for readability:

 print(list(itertools.chain.from_iterable( range( int(ranges[0]), int(ranges[1])+1 ) for ranges in ( (el+[el[0]])[:2] # Allows to get rid of the ternary condition by always adding a duplicate of the first element if it is alone for el in (miniRange.split('-') for miniRange in s.split(',')) ) ))) 
0
source share

All Articles