patternpythonModerate
Grouping consecutive numbers into ranges in Python 3.2
Viewed 0 times
groupingintonumbersrangespythonconsecutive
Problem
The following is a function that I wrote to display page numbers as they appear in books.
If you enter the list
This seemed like a nice example of how the dictionary data type can be used in Python.
Is there is an even more code-efficient way to do this?
If you enter the list
[1,2,3,6,7,10], for example, it would return:1-3,6-7,10This seemed like a nice example of how the dictionary data type can be used in Python.
Is there is an even more code-efficient way to do this?
def formatpagelist (numberlist):
tempdic={}
returnstring=''
for number in numberlist:
if number-1 in tempdic.keys():
tempdic[number-1]=number
elif number-1 in tempdic.values():
for key in tempdic.keys():
if number-1==tempdic[key]: foundkey=key
tempdic[foundkey]=number
else:
tempdic[number]=0
keylist=list(tempdic.keys())
keylist.sort()
for key in keylist:
if tempdic[key]>0:
returnstring+=(str(key)+'-'+str(tempdic[key])+',')
else: returnstring+=str(key)+','
return returnstringSolution
You could use this one-liner to generate groups of consecutive integers in a list:
Then to finish it off, generate the string from the groups.
This assumes they are in sorted order and there are no duplicates. If not sorted, add a
from itertools import groupby, count
groupby(numberlist, lambda n, c=count(): n-next(c))Then to finish it off, generate the string from the groups.
def as_range(iterable): # not sure how to do this part elegantly
l = list(iterable)
if len(l) > 1:
return '{0}-{1}'.format(l[0], l[-1])
else:
return '{0}'.format(l[0])
','.join(as_range(g) for _, g in groupby(numberlist, key=lambda n, c=count(): n-next(c)))
# '1-3,6-7,10'This assumes they are in sorted order and there are no duplicates. If not sorted, add a
sorted() call on numberlist beforehand. If there's duplicates, make it a set beforehand.Code Snippets
from itertools import groupby, count
groupby(numberlist, lambda n, c=count(): n-next(c))def as_range(iterable): # not sure how to do this part elegantly
l = list(iterable)
if len(l) > 1:
return '{0}-{1}'.format(l[0], l[-1])
else:
return '{0}'.format(l[0])
','.join(as_range(g) for _, g in groupby(numberlist, key=lambda n, c=count(): n-next(c)))
# '1-3,6-7,10'Context
StackExchange Code Review Q#5196, answer score: 18
Revisions (0)
No revisions yet.