In a Pylons webapp, I need to take a string such as "<3, 45, 46, 48-51, 77" and create a list of ints (which are actually IDs of objects) to search on.
Any suggestions on ways to do this? I'm new to Python, and I haven't found anything out there that helps with this kind of thing.
The list would be: [1, 2, 3, 45, 46, 48, 49, 50, 51, 77]
Use parseIntSet from here
I also like the pyparsing implementation in the comments at the end.
The parseIntSet has been modified here to handle "<3"-type entries and to only spit out the invalid strings if there are any.
#! /usr/local/bin/python
import sys
import os
# return a set of selected values when a string in the form:
# 1-4,6
# would return:
# 1,2,3,4,6
# as expected...
def parseIntSet(nputstr=""):
selection = set()
invalid = set()
# tokens are comma seperated values
tokens = [x.strip() for x in nputstr.split(',')]
for i in tokens:
if len(i) > 0:
if i[:1] == "<":
i = "1-%s"%(i[1:])
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
if len(invalid) > 0:
print "Invalid set: " + str(invalid)
return selection
# end parseIntSet
print 'Generate a list of selected items!'
nputstr = raw_input('Enter a list of items: ')
selection = parseIntSet(nputstr)
print 'Your selection is: '
print str(selection)
And here's the output from the sample run:
$ python qq.py
Generate a list of selected items!
Enter a list of items: <3, 45, 46, 48-51, 77
Your selection is:
set([1, 2, 3, 45, 46, 77, 48, 49, 50, 51])
I've created a version of @vartec's solution which I feel is more readable:
def _parse_range(numbers: str):
for x in numbers.split(','):
x = x.strip()
if x.isdigit():
yield int(x)
elif x[0] == '<':
yield from range(0, int(x[1:]))
elif '-' in x:
xr = x.split('-')
yield from range(int(xr[0].strip()), int(xr[1].strip())+1)
else:
raise ValueError(f"Unknown range specified: {x}")
In the process, the function became a generator :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With