0

I have this list:

[29, 64, 65, 66, 128, 129, 130, 166, 167, 168, 184, 185, 186, 215, 216, 217, 237, 238, 239, 349, 350, 351, 443, 483, 484, 485, 495, 496, 497, 526, 527, 528, 542, 543, 544, 564, 565, 566]

and i want to separate them that if the difference between the element and the next one different from 1, the code saves the next elements in another lit like

list1=[29]
liste2=[64, 65, 66]
liste3=[128, 129, 130]
liste3=[166, 167, 168]

until the end

wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 3
    Does this answer your question? [Split a list in sublists based on the difference between consecutive values](https://stackoverflow.com/questions/52005258/split-a-list-in-sublists-based-on-the-difference-between-consecutive-values) – Harun Yilmaz Aug 27 '21 at 14:21
  • is this list sorted always? – Epsi95 Aug 27 '21 at 14:24
  • 1
    @Epsi95 If it weren't, you'd just have to sort it before starting. The only other option I can think of involves a list of lists and checking every individual one to insert an element, which is *O(n^2)*. – wjandrea Aug 27 '21 at 14:28
  • I think it is possible with O(nlong) + O(n) ~ O(nlogn), O(nlogn) comes from sorting. I would traverse the sorted array and check for difference 1 and keep on making the group. @wjandrea – Epsi95 Aug 27 '21 at 14:38
  • @Epsi95 That's exactly what I had in mind. See [this answer](/a/52005482/4518341) for an *O(n)* implementation, assuming sorted input. Sorting a list (if needed) is *O(n log n)*. – wjandrea Aug 27 '21 at 14:52

2 Answers2

3

Using numpy you could do this in a single line:

import numpy as np
lst = [29, 64, 65, 66, 128, 129, 130, 166, 167, 168, 184, 185, 186, 215, 216, 217, 237, 238, 239, 349, 350, 351, 443, 483, 484, 485, 495, 496, 497, 526, 527, 528, 542, 543, 544, 564, 565, 566]
[x.tolist() for x in np.split(lst, np.where(np.diff(lst) > 1)[0]+1)]

Output:

[[29],
 [64, 65, 66],
 [128, 129, 130],
 [166, 167, 168],
 [184, 185, 186],
 [215, 216, 217],
 [237, 238, 239],
 [349, 350, 351],
 [443],
 [483, 484, 485],
 [495, 496, 497],
 [526, 527, 528],
 [542, 543, 544],
 [564, 565, 566]]

Edit 1: To store each list to separate variables (Not Recommended)

sub_lists = [x.tolist() for x in np.split(lst, np.where(np.diff(lst) > 1)[0]+1)]
for i in range(1, len(sub_lists)+1):
    globals()['list_%s' % i] = sub_lists[i-1]

Output:

print(list_1)
>> [29]

print(list_2)
>> [64, 65, 66]

Note: It is not recommended to have individual variables for multiple reasons, especially in the scenarios where the number of variables can explode based on the condition.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
heretolearn
  • 6,387
  • 4
  • 30
  • 53
  • Hi I just wanna add on to the answer you have given. Since the output he wants is to store each list into a variable, I believe you could use ```exec()``` to do so (highly not recommended though but should give you the result Sarah wants) ```for key, i in enumerate(new_list): exec(f'liste{key+1} = i')``` new_list is the list created using the code above provided by @heretolearn! cheers – Owenn Aug 27 '21 at 14:52
  • @Owenn, Thanks for the suggestion. I have updated the code to create dynamic variables and save the list value based on the number of sub-lists after the split. – heretolearn Aug 27 '21 at 15:09
  • 2
    I recommend advising OP against individual variable names. See [this answer](/a/38972761/4518341) for an explanation. Either way, putting the variables only in the global namespace could be a bad idea, for example if this code will ultimately go into a function, you'd be polluting globals with vars that should be local, but `locals()` is not assignable. – wjandrea Aug 27 '21 at 15:18
  • 1
    Yes, i agree on the point of having individual variables, specially when we don't know the number of sublist the main list can break it. Will add the note to my answer. Thanks – heretolearn Aug 27 '21 at 15:25
0

I believe this should be what you are looking for:

sort_me = [29, 64, 65, 66, 128, 129, 130, 166, 167, 168, 184, 185, 186, 215, 216, 217, 237, 238, 239, 349, 350, 351, 443, 483, 484, 485, 495, 496, 497, 526, 527, 528, 542, 543, 544, 564, 565, 566]

sorted_lists = list()

last_num = sort_me[0]  # get the  first index of the list to be the last number that has been evaluated
current_list = [sort_me[0]]  # get first index fo list prepared for for loop

# iterate over all numbers in the list
for i in range(1, len(sort_me)):
    num = sort_me[i]  # get the next number
    if num == last_num + 1:  # check if it meets the criteria to be put into list
        current_list.append(num)  # add number to the list
    else:
        sorted_lists.append(current_list)  # add list to list of lists (say that 10 times fast)
        current_list = [num]  # start new list
    last_num = num  # save last num checked as this iteration's number

if len(current_list) > 0:
    sorted_lists.append(current_list)

# print them to show that the lists are correct (chnage this bit to do what you want with them)
for ls in sorted_lists:
    print(ls)

EDIT added line that missed the last list, should be working fine now.

Mitchnoff
  • 495
  • 2
  • 7