Reputation: 453
I want to have a list of lists with sequences of numbers that are continuous
I have a sorted list of integers liek this
[1,2,3,4,6,7,9,10,12,13,14,17,18,19,21]
I cant seem to find a decent algorithm for this ( looked up DP, but that doesnt look like my case)
I want an output like this
[ [1,2,3,4], [6,7], [9,10], [12,13,14], [17,18,19] , [21]
Upvotes: 2
Views: 1335
Reputation: 42133
It wouldn't be as efficient as numpy, but you could use reduce() from functools:
nums = [1, 2, 3, 4, 6, 7, 9, 10, 12, 13, 14, 17, 18, 19, 21]
from functools import reduce
groups = reduce(lambda a,b: a+[[b]] if a[-1][-1]!=b-1 else a[:-1]+[a[-1]+[b]],nums[1:],[nums[:1]])
# [[1, 2, 3, 4], [6, 7], [9, 10], [12, 13, 14], [17, 18, 19], [21]]
Upvotes: 0
Reputation: 88276
For a better performance you might want to try using numpy. Start by obtaining the indices where the first differences are greater than 1
using np.diff
, and use them to split the array in several chunks with np.split
:
import numpy as np
a = np.array([1,2,3,4,6,7,9,10,12,13,14,17,18,19,21])
np.split(a,np.flatnonzero(np.diff(a) > 1) + 1)
[array([1, 2, 3, 4]),
array([6, 7]),
array([ 9, 10]),
array([12, 13, 14]),
array([17, 18, 19]),
array([21])]
Upvotes: 4
Reputation: 26325
You can use this itertools recipe. It uses itertools.groupby
to group consecutive runs by taking the difference in range using enumerate
so all increasing numbers appear in the same group.
Demo:
from operator import itemgetter
from itertools import groupby
data = [1,2,3,4,6,7,9,10,12,13,14,17,18,19,21]
result = [list(map(itemgetter(1), g)) for _, g in groupby(enumerate(data), lambda x: x[0] - x[1])]
print(result)
Output:
[[1, 2, 3, 4], [6, 7], [9, 10], [12, 13, 14], [17, 18, 19], [21]]
Upvotes: 2
Reputation: 59731
Here is one way to do that:
nums = [1, 2, 3, 4, 6, 7, 9, 10, 12, 13, 14, 17, 18, 19, 21]
# Find sequence boundaries
splits = [i + 1 for i, (n1, n2) in enumerate(zip(nums, nums[1:])) if n1 + 1 != n2]
splits.insert(0, 0)
splits.append(len(nums))
# Make subsequences
seqs = [nums[s1:s2] for s1, s2 in zip(splits, splits[1:])]
print(seqs)
# [[1, 2, 3, 4], [6, 7], [9, 10], [12, 13, 14], [17, 18, 19], [21]]
Or if you prefer a more "traditional" for loop:
nums = [1, 2, 3, 4, 6, 7, 9, 10, 12, 13, 14, 17, 18, 19, 21]
seqs = [[nums[0]]]
for n in nums[1:]:
if n != seqs[-1][-1] + 1:
seqs.append([n])
else:
seqs[-1].append(n)
print(seqs)
# [[1, 2, 3, 4], [6, 7], [9, 10], [12, 13, 14], [17, 18, 19], [21]]
Upvotes: 3