Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将连续整数分组在一起_Python_Algorithm_List - Fatal编程技术网

Python 将连续整数分组在一起

Python 将连续整数分组在一起,python,algorithm,list,Python,Algorithm,List,具有以下代码: 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 in

具有以下代码:

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)是现有列表中的最后一项,则不希望为此项创建另一个列表。 i、 e.在1-5范围内,当我们到达
    3
    时,不要创建列表
    3,4
    ,而是将
    3
    附加到现有列表
    [1,2]
我当前的迭代运行得很好,但是由于c.items()中的x,e的
检查,列表越大,迭代速度就越慢

如何在保持相同结果的同时加快速度

新解决方案(使用19000个整数的输入列表,从13秒到0.03秒):

c={}
i=0
最后的列表=无
而i
一个人可以用
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
integers=[1,2,3,4,5,6,8,9,10,11,14,16,18,26,27,29,30,34,35,39,48,64,65]
助手=[]
计数器=0
当计数器
上面的算法假设输入列表已经排序。这给了我们巨大的优势。同时,在运行此算法之前,可以显式地对整数列表进行排序。然后,解决方案的总复杂性将是:
O(n*logn)+O(n)
,这是有效的
O(n*logn)
。而
O(n*logn)
是排序过程的复杂性


我建议大家记住这一非常有用的技巧,即在处理未来使用的任务之前使用排序。

有一个很棒的库,名为:
连续组()

输出:

{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]}

还有一条注释,由于集合是无序的,所以在转换到集合和从集合转换到集合后,您需要进行排序。

下面是一个简单的实现,它使用列表切片实现了您想要的:

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
类型没有排序。

如果使用
for
循环并只跟踪当前列表,则解决方案很简单。当你发现差距时,别忘了列一个新的清单:

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

由于您有连续数字的列表,我建议您使用
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)

您可以尝试使用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}]

您正在处理一个已排序的整数列表。所以你知道你看的下一个数字会比上一个数字大。所以它可以进入最近的连续整数列表,也可以开始一个新的列表。如果您只跟踪最近使用的x,e,在c.items()中,没有理由使用
,但是我如何知道它是否在最近的列表中,或者是否要开始一个新的列表?i、 e.1,2,3,8。。仅仅因为8>3并不意味着它在1,2,3列表中。我是否仍然需要检查
8-last integer==1
?在调用
list(set(…)
之后进行排序是的,您仍然需要检查。但您只需检查最近使用的列表。@sk099。所以检查一下……不幸的是,这根本不能解决问题。其想法是保留一个列表字典,其中字典的键是连续数字范围的开始。如果迭代中的下一个数字不能添加到最后一个列表中,即当前_integer-最后_integer==1,则创建一个新的dict条目,并将该int作为键。我不认为给出问题的完整解决方案是一个好主意。我只是想给你一个提示,将来如何处理这个问题和类似的问题。将计数器的while改为
,枚举中的数字(ints):
@madpysicast当然可以,但我只是尽量避免所有python特有的东西。整数中的数字不特定于python,甚至不需要计数器
?或者只是为了安全起见?如果在将其转换为集合之前进行排序,则无法保证当您转换回列表时,它将被排序。我需要开始进一步探索此模块。谢谢你,克里斯!
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}]