簡體   English   中英

將連續的整數組合在一起

[英]Group consecutive integers together

有以下代碼:

import sys


ints = [1,2,3,4,5,6,8,9,10,11,14,34,14,35,16,18,39,10,29,30,14,26,64,27,48,65]
ints.sort()
ints = list(set(ints))

c = {}

for i,v in enumerate(ints):

    if i+1 >= len(ints):
        continue

    if ints[i+1] == v + 1 or ints[i-1] == v - 1:

        if len(c) == 0:
            c[v] = [v]
            c[v].append(ints[i+1])
        else:
            added=False
            for x,e in c.items():
                last = e[-1]
                if v in e:
                    added=True
                    break

                if v - last == 1:
                    c[x].append(v)
                    added=True

            if added==False:
                c[v] = [v]
    else:
        if v not in c:
            c[v] = [v]



print('input ', ints)
print('output ', c))

目標:

給定一個整數列表,創建一個包含連續整數的字典,以減少列表的總長度。

這是我當前解決方案的輸出:

input  [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 16, 18, 26, 27, 29, 30, 34, 35, 39, 48, 64, 65]
output  {1: [1, 2, 3, 4, 5, 6], 8: [8, 9, 10, 11], 14: [14], 16: [16], 18: [18], 26: [26, 27], 29: [29, 30], 34: [34, 35], 39: [39], 48: [48], 64: [64]}

條件/限制:

  • 如果當前整數是現有列表中的a)或b)是現有列表中的最后一項,我們不希望為此項創建另一個列表。 即在1-5范圍內,當我們到達3 ,不要創建列表3,4 ,而是將3附加到現有列表[1,2]

我當前的迭代工作正常,但是由於for x,e in c.items()現有列表檢查中的for x,e in c.items()列表越大,它就會指數越慢。

如何在實現相同結果的同時加快速度?

新解決方案(使用19,000個整數的輸入列表,從13秒到0.03秒):

c = {}

i = 0

last_list = None

while i < len(ints):
    cur = ints[i]

    if last_list is None:
        c[cur] = [cur]
        last_list = c[cur]

    else:

        if last_list[-1] == cur-1:
            last_list.append(cur)
        else:
            c[cur] = [cur]
            last_list = c[cur]

    i += 1

由於你有連續數字的列表,我建議你使用range對象而不是list s:

d, head = {}, None
for x in l:
    if head is None or x != d[head].stop:
        head = x
    d[head] = range(head, x+1)

如果您使用for循環並且只是跟蹤當前列表,解決方案很簡單。 當您發現差距時,不要忘記制作新的清單:

result = {}
cl = None
for i in ints:
    if cl is None or i - 1 != cl[-1]:
        cl = result.setdefault(i, [])
    cl.append(i)

有一個很棒的庫叫做more_itertools ,它有一個名為: consecutive_groups()

import more_itertools as mit
x = [1,2,3,4,5,6,8,9,10,11,14,34,14,35,16,18,39,10,29,30,14,26,64,27,48,65]
x = [list(j) for j in mit.consecutive_groups(sorted(list(set(x))))]
# [[1, 2, 3, 4, 5, 6], [8, 9, 10, 11], [14], [16], [18], [26, 27], [29, 30], [34, 35], [39], [48], [64, 65]]
dct_x = {i[0]: i for i in x}
print(dct_x)

輸出:

{1: [1, 2, 3, 4, 5, 6], 8: [8, 9, 10, 11], 14: [14], 16: [16], 18: [18], 26: [26, 27], 29: [29, 30], 34: [34, 35], 39: [39], 48: [48], 64: [64, 65]}

還有一個注釋,您希望在轉換為集合之后進行排序,因為集合是無序的。

可以用O(n) (線性)復雜度來解決這個任務。 保持簡單:

integers = [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 16, 18, 26, 27, 29, 30, 34, 35, 39, 48, 64, 65]

helper = []
counter = 0
while counter < len(integers):
  if not helper or helper[-1] + 1 != integers[counter]:
    print('gap found', integers[counter])  # do your logic
  helper.append(integers[counter])
  counter += 1

上面的算法假定輸入列表已經排序。 它給了我們巨大的優勢。 同時,在運行此算法之前,可以明確地對整數列表進行排序。 然后,解的總復雜度為: O(n * log n) + O(n) ,其有效地為O(n * log n) O(n * log n)是排序過程的復雜性。

我建議記住這個非常有用的技巧,即在接近未來用途的任務之前使用排序。

這是一個簡單的實現,使用列表切片實現您的目標:

integers = [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 16, 18, 26, 27, 29, 30, 34, 35, 39, 48, 64, 65]
for i, integer in enumerate(integers):
    if i == 0:
        out_dict = {}
        start = 0
    else:
        if integer != prev_integer + 1:
            out_dict[integers[start]] = integers[start:i]
            start = i
        if i == len(integers) - 1:
            out_dict[integers[start]] = integers[start:]
    prev_integer = integer

>>>out_dict =  {1: [1, 2, 3, 4, 5, 6], 8: [8, 9, 10, 11], 14: [14], 16: [16], 18: [18], 26: [26, 27], 29: [29, 30], 34: [34, 35], 39: [39], 48: [48], 64: [64]}

注意:字典可能不會按升序鍵排序,因為dict類型沒有排序。

您可以嘗試使用itertools,但我想嘗試遞歸:

input_dta=[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 14, 16, 18, 26, 27, 29, 30, 34, 35, 39, 48, 64, 65]

final_=[]

def consecutives(data):
    sub_final=[]

    if not data:
        return 0
    else:
        for i,j in enumerate(data):
            try:

                if abs(data[i]-data[i+1])==1:
                    sub_final.extend([data[i],data[i+1]])



                else:
                    if sub_final:
                        final_.append(set(sub_final))




                    return consecutives(data[i+1:])
            except IndexError:
                pass

    final_.append(set(sub_final))


consecutives(input_dta)



print(final_)

輸出:

[{1, 2, 3, 4, 5, 6}, {8, 9, 10, 11}, {26, 27}, {29, 30}, {34, 35}, {64, 65}]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM