I would like to be able to convert a string such as "1,2,5-7,10" to a python list such as [1,2,5,6,7,10]. I looked around and found this, but I was wondering if there is a clean and simple way to do this in Python.
8 Answers
def f(x):
result = []
for part in x.split(','):
if '-' in part:
a, b = part.split('-')
a, b = int(a), int(b)
result.extend(range(a, b + 1))
else:
a = int(part)
result.append(a)
return result
>>> f('1,2,5-7,10')
[1, 2, 5, 6, 7, 10]
-
4This would make a nice generator. – Neil G Jun 19 '11 at 21:38
-
Not exploding on leading or trailing comma is achieved by replacing the else with ```elif part != '':``` – Akom Mar 23 '20 at 17:02
I was able to make a true comprehension on that question:
>>> def f(s):
return sum(((list(range(*[int(j) + k for k,j in enumerate(i.split('-'))]))
if '-' in i else [int(i)]) for i in s.split(',')), [])
>>> f('1,2,5-7,10')
[1, 2, 5, 6, 7, 10]
>>> f('1,3-7,10,11-15')
[1, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15]
the other answer that pretended to have a comprehension was just a for loop because the final list was discarded. :)
For python 2 you can even remove the call to list
!

- 32,262
- 10
- 90
- 115
This might be an overkill, but I just like pyparsing:
from pyparsing import *
def return_range(strg, loc, toks):
if len(toks)==1:
return int(toks[0])
else:
return range(int(toks[0]), int(toks[1])+1)
def parsestring(s):
expr = Forward()
term = (Word(nums) + Optional(Literal('-').suppress() + Word(nums))).setParseAction(return_range)
expr << term + Optional(Literal(',').suppress() + expr)
return expr.parseString(s, parseAll=True)
if __name__=='__main__':
print parsestring('1,2,5-7,10')
Very short, and elegant (imho):
>>> txt = "1,2,5-7,10"
>>> # construct list of xranges
>>> xranges = [(lambda l: xrange(l[0], l[-1]+1))(map(int, r.split('-'))) for r in txt.split(',')]
>>> # flatten list of xranges
>>> [y for x in xranges for y in x]
[1, 2, 5, 6, 7, 10]

- 2,816
- 20
- 14
No comprehension beats mine!
import re
def convert(x):
return sum((i if len(i) == 1 else list(range(i[0], i[1]+1))
for i in ([int(j) for j in i if j] for i in
re.findall('(\d+),?(?:-(\d+))?', x))), [])
The best part is that I use variable i
twice in the middle of the comprehension.
>>> convert('1,2,5-7,10')
[1, 2, 5, 6, 7, 10]
From here: https://gist.github.com/raczben/76cd1229504d82115e6427e00cf4742c
def number(a, just_try=False):
"""
Parse any representation of number from string.
"""
try:
# First, we try to convert to integer.
# (Note, that all integer can be interpreted as float and hex number.)
return int(a)
except:
# The order of the following convertions doesn't matter.
# The integer convertion has failed because `a` contains hex digits [x,a-f] or a decimal
# point ['.'], but not both.
try:
return int(a, 16)
except:
try:
return float(a)
except:
if just_try:
return a
else:
raise
def str2numlist(s):
"""
Convert a string parameter to iterable object.
"""
return [y for x in s.split(',') for y in str_ranges_to_list(x) ]
def str_ranges_to_list(s):
"""
Convert a string parameter to iterable object.
"""
s = s.strip()
try:
begin,end=s.split(':')
return range(number(begin), number(end))
except ValueError: # not enough values to unpack
return [number(s)]

- 3,454
- 1
- 33
- 65
Ugh, the answers are so verbose! Here is a short and elegant answer:
def rangeString(commaString):
def hyphenRange(hyphenString):
x = [int(x) for x in hyphenString.split('-')]
return range(x[0], x[-1]+1)
return chain(*[hyphenRange(r) for r in commaString.split(',')])
Demo:
>>> list( f('1,2,5-7,10') )
[1, 2, 5, 6, 7, 10]
Easily modifiable to handle negative numbers or return a list. Also will need from itertools import chain
, but you can substitute sum(...,[])
for it if you are not working with range
objects (or sum(map(list,iters),[])
) and you don't care about being lazy.

- 88,546
- 24
- 137
- 145
Initializing string
test_str = "1, 4-6, 8-10, 11"
printing original string
print("The original string is : " + test_str)
Convert String ranges to list
res = sum(((list(range(*[int(b) + c
for c, b in enumerate(a.split('-'))]))
if '-' in a else [int(a)]) for a in test_str.split(', ')), [])
printing result
print("List after conversion from string : " + str(res))

- 540
- 2
- 4
- 15