Reputation: 173
I want to separate list of elements into nested list, each sub list having consecutive elements. If an element doesn't have a consecutive element, it should have in single list.
Input:
l1 = [1, 2, 3, 11, 12, 13, 23, 33, 34, 35, 45]
l2 = [11, 12, 13, 22, 23, 24, 33, 34]
l3 = [1, 2, 3, 11, 12, 13, 32, 33, 34, 45]
expected output:
l1 = [[1, 2, 3], [11, 12, 13], [23], [33, 34, 35], [45]]
l2 = [[11, 12, 13], [22, 23, 24], [33, 34]]
l3 = [[1, 2, 3], [11, 12, 13], [32, 33, 34], [45]]
I have tried the code below but it is not giving the expected result, printing an empty list:
def split_into_list(l):
t = []
for i in range(len(l) - 1):
if abs(l[i] - l[i + 1]) == 0:
t.append(l[i])
elif abs(l[i] - l[i + 1]) != 0 and abs(l[i - 1] - l[i]) == 0:
t.append(l[i])
yield t
split_into_list(l[i:])
if i + 1 == len(l):
t.append(l[i])
yield t
l = [1, 2, 3, 11, 12, 13, 32, 33, 34, 45]
li = []
li.append(split_into_list(l))
for i in li:
print(i, list(i))
Upvotes: 2
Views: 540
Reputation: 114440
This is something that lends itself well to a numpy solution using diff
and split
:
def consecutives(x):
np.split(x, np.flatnonzero(np.diff(x) != 1) + 1)
For example, consecutives(l1)
will result in
[array([1, 2, 3]),
array([11, 12, 13]),
array([23]),
array([33, 34, 35]),
array([45])]
If you need nested lists, you can apply list
or ndarray.tolist
:
def consecutives(x):
return [a.tolist() for a in np.split(x, np.flatnonzero(np.diff(x) != 1) + 1)]
Now the result of consecutives(l1)
is
[[1, 2, 3], [11, 12, 13], [23], [33, 34, 35], [45]]
Upvotes: 0
Reputation: 103
def split_into_list(l):
t = []
temp = [l[0]]
prev = l[0]
for i in l[1:]:
if i == prev+1:
temp.append(i)
else:
t.append(temp)
temp = [i]
prev = i
return t
Mind that all solutions so far relie on sorted lists, which you didn't expicitly specify in your question.
Upvotes: 0
Reputation: 5226
def split_into_list(l):
result = [[]]
for i, elt in enumerate(l[1:]):
diff = abs(elt - l[i])
if diff == 1:
# still the same group
result[-1].append(elt)
else:
# new group
result.append([elt])
return result
l = [1,2,3,11,12,13,32,33,34,45]
print(split_into_list(l))
yields
[[2, 3], [11, 12, 13], [32, 33, 34], [45]]
Upvotes: 0
Reputation: 92874
Shorter approach with custom split_adjacent
function:
def split_adjacent(lst):
res = [[lst[0]]] # start/init with the 1st item/number
for i in range(1, len(lst)):
if lst[i] - res[-1][-1] > 1: # compare current and previous item
res.append([])
res[-1].append(lst[i])
return res
l1 = [1, 2, 3, 11, 12, 13, 23, 33, 34, 35, 45]
l2 = [11, 12, 13, 22, 23, 24, 33, 34]
l3 = [1, 2, 3, 11, 12, 13, 32, 33, 34, 45]
print(split_adjacent(l1))
print(split_adjacent(l2))
print(split_adjacent(l3))
Final output:
[[1, 2, 3], [11, 12, 13], [23], [33, 34, 35], [45]]
[[11, 12, 13], [22, 23, 24], [33, 34]]
[[1, 2, 3], [11, 12, 13], [32, 33, 34], [45]]
Upvotes: 2