Список разбиения Python на основе пропущенных чисел в последовательности - PullRequest
18 голосов
/ 30 июня 2010

Я ищу самый питонический способ разбить список чисел на меньшие списки на основе числа, отсутствующего в последовательности. Например, если начальный список был:

seq1 = [1, 2, 3, 4, 6, 7, 8, 9, 10]

функция выдаст:

[[1, 2, 3, 4], [6, 7, 8, 9, 10]]

или

seq2 = [1, 2, 4, 5, 6, 8, 9, 10]

приведет к:

[[1, 2], [4, 5, 6], [8, 9, 10]]

Ответы [ 5 ]

38 голосов
/ 30 июня 2010

Из документации python :

>>> # Find runs of consecutive numbers using groupby.  The key to the solution
>>> # is differencing with a range so that consecutive numbers all appear in
>>> # same group.
>>> data = [ 1,  4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
>>> for k, g in groupby(enumerate(data), lambda (i,x):i-x):
...     print map(itemgetter(1), g)
...
[1]
[4, 5, 6]
[10]
[15, 16, 17, 18]
[22]
[25, 26, 27, 28]

Функция groupby () из модуля itertools генерирует разрыв каждый раз, когда ключевая функция меняет свое возвращаемое значение. Хитрость в том, что возвращаемое значение - это число в списке за вычетом положения элемента в списке. Эта разница изменяется при наличии разрыва в числах.

Функция itemgetter () из операторского модуля , вам придется импортировать его и модуль itertools для работы этого примера.

Полный пример с вашими данными:

>>> from operator import itemgetter
>>> from itertools import *
>>> seq2 = [1, 2, 4, 5, 6, 8, 9, 10]
>>> list = []
>>> for k, g in groupby(enumerate(seq2), lambda (i,x):i-x):
...     list.append(map(itemgetter(1), g))
... 
>>> print list
[[1, 2], [4, 5, 6], [8, 9, 10]]

Или как списочное понимание:

>>> [map(itemgetter(1), g) for k, g in groupby(enumerate(seq2), lambda (i,x):i-x)]
[[1, 2], [4, 5, 6], [8, 9, 10]]
5 голосов
/ 02 февраля 2017

Это решение, которое работает в Python 3 (на основе предыдущих ответов, которые работают только в Python 2).

>>> from operator import itemgetter
>>> from itertools import *
>>> groups = []
>>> for k, g in groupby(enumerate(seq2), lambda x: x[0]-x[1]):
>>>     groups.append(list(map(itemgetter(1), g)))
... 
>>> print(groups)
[[1, 2], [4, 5, 6], [8, 9, 10]]

или в виде списка

>>> [list(map(itemgetter(1), g)) for k, g in groupby(enumerate(seq2), lambda x: x[0]-x[1])]
[[1, 2], [4, 5, 6], [8, 9, 10]]

Изменения былинеобходимо, потому что

  • Удаление распаковки параметра кортежа PEP 3113
  • карта, возвращающая итератор вместо списка
5 голосов
/ 30 июня 2010

Еще один вариант, который не требует itertools и т. Д.

>>> data = [1, 4, 5, 6, 10, 15, 16, 17, 18, 22, 25, 26, 27, 28]
>>> spl = [0]+[i for i in range(1,len(data)) if data[i]-data[i-1]>1]+[None]
>>> [data[b:e] for (b, e) in [(spl[i-1],spl[i]) for i in range(1,len(spl))]]
... [[1], [4, 5, 6], [10], [15, 16, 17, 18], [22], [25, 26, 27, 28]]
1 голос
/ 19 января 2019

Мне больше нравится этот вариант, потому что для первого случая он не требует дополнительных библиотек или специальной обработки:

a = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 20, 21, 22]
b = []
subList = []
prev_n = -1

for n in a:
    if prev_n+1 != n:            # end of previous subList and beginning of next
        if subList:              # if subList already has elements
            b.append(subList)
            subList = []
    subList.append(n)
    prev_n = n

if subList:
    b.append(subList)

print a
print b

Вывод:

[1, 2, 3, 4,5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 20, 21, 22]

[[1, 2, 3, 4, 5, 6, 7,8], [10, 11, 12], [15, 16, 17, 18], [20, 21, 22]]

0 голосов
/ 16 марта 2018

Мой путь

alist = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 20, 21, 22]
newlist = []
start = 0
end = 0
for index,value in enumerate(alist):
    if index < len(alist)-1:
        if alist[index+1]> value+1:
            end = index +1
            newlist.append(alist[start:end])
            start = end
    else:
            newlist.append(alist[start: len(alist)])
print(newlist)

Результат

[[1, 2, 3, 4, 5, 6, 7, 8], [10, 11, 12], [15, 16, 17, 18], [20, 21, 22]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...