简体   繁体   中英

Group consecutive numbers from a list of numbers into a list of tuples using base python (NO itertools or more itertools allowed)

I would like to turn a list like this:

L1 = [3, 5, 6, 7, 8, 9, 11, 13, 14]

Into a list of groups of consecutive numbers where each group is a tuple using base python (NO itertools or more itertools allowed).

Final list should look like this: [(3,), (5, 6, 7, 8, 9), (11,), (13, 14)]

I came to this result by using more_itertools

import more_itertools as mit

[tuple(group) for group in mit.consecutive_groups(sorted(L1))]

Result: [(3,), (5, 6, 7, 8, 9), (11,), (13, 14)]

Use a generator ( consecutive_groups is generator):

L1 = [3, 5, 6, 7, 8, 9, 11, 13, 14]


def group_consecutive(l):
    r = []
    for e in l:
        if not r:
            r.append(e)
        elif e - r[-1] == 1:
            r.append(e)
        else:
            yield tuple(r)
            r = [e]
    yield tuple(r)


print(list(group_consecutive(L1)))  # [(3,), (5, 6, 7, 8, 9), (11,), (13, 14)]

Generator and using List slicing:

L1 = [3, 5, 6, 7, 8, 9, 11, 13, 14]


def group_consecutive(l):
    start = 0
    stop = 0
    for i, e in enumerate(l):
        if not stop or l[i] - l[i-1] == 1:
            stop += 1
        else:
            yield tuple(l[start:stop])
            start = i
            stop = i + 1
    yield tuple(l[start:stop])


print(list(group_consecutive(L1)))  # [(3,), (5, 6, 7, 8, 9), (11,), (13, 14)]

Your version is probably better, but here's a recursive approach.

x = [3, 5, 6, 7, 8, 9, 11, 13, 14]

def f(x):
    # if x is an empty list the grouping is already done.
    if x == []:
        return []
    # h is the first element (wrapped in a list), y is the rest.
    h, y = [x[0]], x[1:]
    # while there remain numbers to group and they follow the element h
    while y != [] and  y[0] == h[-1] + 1:
        # keep appending them to the current group
        h.append(y.pop(0))
    # recursive call
    return [tuple(h)] + f(y)
print(f(x))
l = [3, 5, 6, 7, 8, 9, 11, 13, 14]


def consecutive_groups(l):
    if not l:
        return []
    current = [l[0]]
    for i, j in zip(l, l[1:]):
        if j - i == 1:
            current.append(j)
        else:
            yield tuple(current)
            current = [j]
    yield tuple(current)

print(list(consecutive_groups(l)))

I suggest you this solution, quite short and readable:

L1 = [3, 5, 6, 7, 8, 9, 11, 13, 14]

r, t = [], []
for i in L1:
    if t and i != t[-1] + 1:
        r.append(tuple(t))
        t.clear()
    t.append(i)
r.append(tuple(t))

print(r)
# [(3,), (5, 6, 7, 8, 9), (11,), (13, 14)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM