2017-03-16 84 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])