I\'m trying to format a list of integers with Python and I\'m having a few difficulties achieving what I\'d like.
Input is a sorted list of Integers:
You can use groupby and count from itertools module like this way:
Edit:
Thanks to @asongtoruin comment. For removing duplicates from the input you can use: sorted(set(a)).
from itertools import groupby, count
a = [1, 2, 3, 6, 8, 9]
clustered = [list(v) for _,v in groupby(sorted(a), lambda n, c = count(): n-next(c))]
for k in clustered:
if len(k) > 1:
print("{0}-{1}".format(k[0], k[-1]))
else:
print("{0}".format(k[0]))
Output:
1-3
6
8-9
Or maybe you can do something like this in order to have a pretty output:
from itertools import groupby, count
a = [1, 2, 3, 6, 8, 9]
clustered = [list(v) for _,v in groupby(sorted(a), lambda n, c = count(): n-next(c))]
out = ", ".join(["{0}-{1}".format(k[0], k[-1]) if len(k) > 1 else "{0}".format(k[0]) for k in clustered ])
print(out)
Output:
1-3, 6, 8-9
Update:
I'm guessing, using itertools modules may confuse many Python's new developers. This is why i decided to rewrite the same solution without importing any package and trying to show what groupby and count are doing behind the scenes:
def count(n=0, step=1):
"""Return an infinite generator of numbers"""
while True:
n += step
yield n
def concat(lst):
"""Group lst elements based on the result of elm - next(_count)"""
_count, out = count(), {}
for elm in sorted(lst):
c = elm - next(_count)
if c in out:
out[c].append(elm)
else:
out[c] = [elm]
return out
def pretty_format(dct):
for _, value in dct.items():
if len(value) > 1:
yield '{}-{}'.format(value[0], value[-1])
else:
yield '{}'.format(value[0])
lst = [1, 2, 3, 6, 8, 9]
dct = concat(lst)
formatted = list(pretty_format(dct))
print(formatted)
Output:
['1-3', '6', '8-9']