You can use groupby and count from the itertools module as follows:
Edit:
Thanks to @asongtoruin comment. To remove duplicates from 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 to get nice 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 suggest that using itertools modules can confuse many Python new developers. This is why I decided to rewrite the same solution without importing the package and not 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']