Formatting consecutive numbers

后端 未结 5 2003
轻奢々
轻奢々 2021-01-18 15:00

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:



        
相关标签:
5条回答
  • 2021-01-18 15:34

    This seems a bit shorter than the current answers but is still pretty readable.

    There might be a nicer way to do it without building an object up with an explicit loop, but I couldn't think of one.

    L = [1, 2, 3, 6, 8, 9]
    
    runs = [[str(L[0])]]
    
    for first, second in zip(L, L[1:]):
        if second == first + 1:
            runs[-1].append(str(second))
        else:
            runs.append([str(second)])
    
    result = ", ".join(["-".join(run) for run in runs])
    
    0 讨论(0)
  • 2021-01-18 15:48
    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.

    0 讨论(0)
  • 2021-01-18 15:48

    Not the most readable solution but gets the job done. One can first determine jumps in your data (jump = difference between two elements is greater than 1). Then you just loop through you original list and collect the respective elements and join them to a string.

    import numpy as np
    
    l = np.array([1, 2, 3, 6, 8, 9])
    
    # find indexes of jumps in your data
    l_diff = np.where(np.diff(l) > 1)[0] + 1
    
    # add one index which makes slicing easier later on
    if l_diff[0] != 0:
        l_diff = np.insert(l_diff, 0, 0)
    
    # add all the data which are groups of consecutive values
    res = []    
    for ix, i in enumerate(l_diff):
        try:
            sl = l[i:l_diff[ix + 1]]
            if len(sl) > 1:
                res.append([sl[0], sl[-1]])
            else:
                res.append(sl)
        # means we reached end of l_diff
        except IndexError:
            sl = l[i:]
            if len(sl) > 1:
                res.append([sl[0], sl[-1]])
            else:
                res.append(sl)
    
    
    # join the data accordingly, we first have to convert integers to strings
    res = ', '.join(['-'.join(map(str, ai)) for ai in res])
    

    Then res is

    '1-3, 6, 8-9'
    
    0 讨论(0)
  • 2021-01-18 15:52

    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

    0 讨论(0)
  • 2021-01-18 15:55

    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']
    
    0 讨论(0)
提交回复
热议问题