2017-03-16 83 views
5

我正在嘗試使用Python格式化整數列表,並且遇到了一些困難,實現了我想要的功能。格式化連續號碼

輸入是整數的排序列表:

list = [1, 2, 3, 6, 8, 9] 

我想它的輸出是一個字符串看起來像這樣:

outputString = "1-3, 6, 8-9" 

到目前爲止,所有我設法實現是這樣的:

outputString = "1-2-3, 6, 8-9" 

我很難告訴我的代碼忽略一個Int如果它已經是連續的。

這裏是我到目前爲止的代碼:

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 

感謝您的幫助和見解:)

+0

我前段時間處理同樣的問題。不幸的是我現在找不到代碼。但是我記得,已經決定「8,9」比「8-9」更具人類可讀性,所以我們只對3個和更多連續的整數使用倒數第一個符號。 – VPfB

回答

5

您可以使用groupbycountitertools模塊像這樣:

編輯:

感謝@asongtoruin的意見。要從輸入中刪除重複項,您可以使用: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])) 

輸出:

1-3 
6 
8-9 

或者,也許你可以做這樣的事情,爲了有一個漂亮的輸出:

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) 

輸出:

1-3, 6, 8-9 
+1

您的輸出是不正確的? – TemporalWolf

+1

對不起,這是一個錯字我正在更新我的答案 –

+0

更新,現在看到:-) –

1

不是最可讀的解決方案,但完成工作。可以首先確定數據中的跳轉(jump =兩個元素之間的差異大於1)。然後,您只需遍歷原始列表並收集各個元素並將它們連接到一個字符串。

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]) 

然後res

'1-3, 6, 8-9' 
2
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 

代碼之後添加這些行。

2

因爲誰張貼了這個解決方案的其他人刪除了他的答案......

這裏有一個O(n)串樓宇解決方案:

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 

repl.it

+0

這一個是相當可讀!但是,輸出具有兩次列表的最後一個索引。 – Yoshiki

+0

@Yoshiki你是對的,我修正了錯誤並更新了我的答案。 – TemporalWolf

1

這似乎比短一點目前的答案,但仍然非常可讀。

可能有更好的方法來做到這一點,而不用建立一個明確的循環的對象,但我想不出一個。

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])