nexla
nexla

Reputation: 453

append continuous sequence of numbers to list

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

Answers (4)

Alain T.
Alain T.

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

yatu
yatu

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

RoadRunner
RoadRunner

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

javidcf
javidcf

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

Related Questions