Python拆分列表基于序列中缺少的数字

bil*_*oot 19 python list sequence

我正在寻找最基本的方法,根据序列中缺少的数字将数字列表拆分成较小的列表.例如,如果初始列表是:

seq1 = [1, 2, 3, 4, 6, 7, 8, 9, 10]
Run Code Online (Sandbox Code Playgroud)

该函数将产生:

[[1, 2, 3, 4], [6, 7, 8, 9, 10]]
Run Code Online (Sandbox Code Playgroud)

要么

seq2 = [1, 2, 4, 5, 6, 8, 9, 10]
Run Code Online (Sandbox Code Playgroud)

会导致:

[[1, 2], [4, 5, 6], [8, 9, 10]]
Run Code Online (Sandbox Code Playgroud)

Mad*_*ist 40

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]
Run Code Online (Sandbox Code Playgroud)

每次key函数更改其返回值时,itertools模块中的groupby()函数都会生成一个中断.诀窍是返回值是列表中的数字减去列表中元素的位置.当数字存在差距时,这种差异会发生变化.

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]]
Run Code Online (Sandbox Code Playgroud)

或者作为列表理解:

>>> [map(itemgetter(1), g) for k, g in groupby(enumerate(seq2), lambda (i,x):i-x)]
[[1, 2], [4, 5, 6], [8, 9, 10]]
Run Code Online (Sandbox Code Playgroud)

  • 我不认为你可以获得比这更pythonic :) (5认同)

小智 5

不需要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]]
Run Code Online (Sandbox Code Playgroud)


小智 5

这是在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]]
Run Code Online (Sandbox Code Playgroud)

或作为列表理解

>>> [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]]
Run Code Online (Sandbox Code Playgroud)

需要进行更改,因为

  • 删除元组参数拆包PEP 3113
  • 映射返回迭代器而不是列表