Daiyue Weng wrote: > Hi, first of all, let me rephase the problem. > > For an arbitrary list of integers (the integers in the list are not > necessary to be sequential), e.g. [1,2,3,6,8,9,10,11,13], > > if a set of consecutive integers having a difference of 1 between them, > put them in a list, i.e. there are two such lists in this example, > > [1,2,3], > > [8,9,10,11], > > and then put such lists in another list (i.e. [[1,2,3], [8,9,10,11]]). Put > the rest integers (non-sequential) in a separated list, i.e. > > `[6, 13]`. > > Note that, the problem only considers sequential integers with step_size = > 1. > > I tried to use itertools.groupby and itertools.count, > > from itertools import groupby, count > lst = [1,2,3,6,8,9,10,11,13] > c = count() > result = [list(g) for i, g in groupby(lst, key=lambda x: x-next(c))] > > but the result is close to the requirement shown as a list of lists, > > [[1, 2, 3], [6], [8, 9, 10, 11], [13]] > > but it didn't separate sequential lists from non-sequential ones. > Also, I couldn't find a way to put [6] and [13] in a single list. > > I have also tried to separate sequential lists from non-sequential ones, > > result = [list(g) for i, g in groupby(lst, key=lambda x: x-next(c) == 1)] > # tried to extract [1,2,3] and [8,9,10,11] from the list > > or > > result = [list(g) for i, g in groupby(lst, key=lambda x: x-next(c) > 1)] # > tried to extract [6] and [13] from the list > > but they all ended up with > > [[1, 2, 3], [6, 8, 9, 10, 11, 13]] > > So two questions here, > > 1. How does itertools.groupby key function work in my case? > > 2. How to improve the program to achieve my goals?
OK, you did at least try this time. So here's my attempt: $ cat consecutive.py from itertools import chain, groupby, islice, tee def lonely(triple): left, value, right = triple if left is not None and value - left == 1: return False if right is not None and right - value == 1: return False return True def grouped(values): left, mid, right = tee(values, 3) triples = zip( chain([None], left), mid, chain(islice(right, 1, None), [None]) ) for key, group in groupby(triples, lonely): yield key, (value for left, value, right in group) def main(): consecutive = [] other = [] values = [1, 2, 3, 6, 8, 9, 10, 11, 13, 17, 19] for is_lonely, group in grouped(values): if is_lonely: other.extend(group) else: consecutive.append(list(group)) print("input") print(" ", values) print() print("consecutive") print(" all ", consecutive) print(" shortest", min(consecutive, key=len)) print(" longest ", max(consecutive, key=len)) print() print("other") print(" ", other) if __name__ == "__main__": main() $ python3 consecutive.py input [1, 2, 3, 6, 8, 9, 10, 11, 13, 17, 19] consecutive all [[1, 2, 3], [8, 9, 10, 11]] shortest [1, 2, 3] longest [8, 9, 10, 11] other [6, 13, 17, 19] $ This is not as efficient as it should be -- the gaps are calculated twice, the check for the first and the last position is repeated on every iteration lots of packing and unpacking... -- either groupby() is the wrong tool or I'm holding it wrong ;) -- https://mail.python.org/mailman/listinfo/python-list