The aim is to find groups of increasing/monotonic numbers given a list of integers. Each item in the resulting group must be of a +1 increment from the previous item
If two consecutive numbers are increasing by one I form a list
(group
) of tuples
of those numbers.
When non-increasing and if the list
(group
) is non-empty, I unpack it and zip
again to rebuild the pair of sequence which were broken by the zip
. I use set
comprehension to eliminate duplicate numbers.
def extract_increasing_groups(seq):
seq = tuple(seq)
def is_increasing(a,b):
return a + 1 == b
def unzip(seq):
return tuple(sorted({ y for x in zip(*seq) for y in x}))
group = []
for a,b in zip(seq[:-1],seq[1:]):
if is_increasing(a,b):
group.append((a,b))
elif group:
yield unzip(group)
group = []
if group:
yield unzip(group)
if __name__ == '__main__':
x = [17, 17, 19, 20, 21, 22, 0, 1, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 14, 14, 28, 29, 30, 31, 32, 33, 34, 35, 36, 40]
for group in extract_increasing_groups(x):
print(group)
Simpler one using set;
from collections import namedtuple
from itertools import islice, tee
def extract_increasing_groups(iterable):
iter1, iter2 = tee(iterable)
iter2 = islice(iter2,1,None)
is_increasing = lambda a,b: a + 1 == b
Igroup = namedtuple('Igroup','group, len')
group = set()
for pair in zip(iter1, iter2):
if is_increasing(*pair):
group.update(pair)
elif group:
yield Igroup(tuple(sorted(group)),len(group))
group = set()
if group:
yield Igroup(tuple(sorted(group)), len(group))
if __name__ == '__main__':
x = [17, 17, 19, 20, 21, 22, 0, 1, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 28, 29, 30, 31, 32, 33, 34, 35, 36, 40]
total = 0
for group in extract_increasing_groups(x):
total += group.len
print('Group: {}\nLength: {}'.format(group.group, group.len))
print('Total: {}'.format(total))