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:
list = [1, 2, 3, 6, 8, 9]
I would like it the output to be a String looking like this:
outputString = "1-3, 6, 8-9"
So far all I managed to achieve is this:
outputString = "1-2-3, 6, 8-9"
I'm having trouble to tell my code to ignore a Int if it was already consecutive.
Here is my code so far:
def format(l):
    i = 0
    outputString = str(l[i])
    for x in range(len(l)-1):
        if l[i + 1] == l[i]+1 :
            outputString += '-' + str(l[i+1])
        else :
            outputString += ', ' + str(l[i+1])
        i = i + 1
    return outputString
Thanks for your help and insights :)
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']
                        list=[1, 2, 3, 4, 6, 10, 11, 12, 13]
y=str(list[0])
for i in range(0, len(list)-1):
    if list[i+1] == list[i]+1 :
        y+= '-' + str(list[i + 1])
    else:
        y+= ',' + str(list[i + 1])
print y
z= y.split(',')
outputString= ''
for i in z:
    p=i.split('-')
    if p[0] == p[len(p)-1]:
        outputString = outputString + str(p[0]) + str(',')
    else:
        outputString = outputString + str(p[0]) + str('-') + str(p[len(p) - 1]) + str(',')
outputString = outputString[:len(outputString) - 1]
print 'final ans: ',outputString
add these lines after your code.
Since the other guy who posted this solution deleted his answer...
Here's a O(n) string building solution:
def stringify(lst):
    result = str(lst[0])
    end = None
    for index, num in enumerate(lst[1:]):
        if num - 1 == lst[index]:  # the slice shifts the index by 1 for us
            end = str(num)
        else:
            if end:
                result += '-' + end
                end = None
            result += ', ' + str(num)
    # Catch the last term
    if end:
        result += '-' + str(num)
    return result
See the repl.it
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