按连续顺序排列的组列表

b10*_*ard 11 python

我有一个整数列表......

[1,2,3,4,5,8,9,10,11,200,201,202]
Run Code Online (Sandbox Code Playgroud)

我想将它们分组到一个列表列表中,其中每个子列表包含其序列尚未被破坏的整数.像这样...

[[1,5],[8,11],[200,202]]
Run Code Online (Sandbox Code Playgroud)

我有一个相当笨重的工作......

lSequenceOfNum = [1,2,3,4,5,8,9,10,11,200,201,202]

lGrouped = []
start = 0
for x in range(0,len(lSequenceOfNum)):
    if x != len(lSequenceOfNum)-1:
        if(lSequenceOfNum[x+1] - lSequenceOfNum[x]) > 1:
            lGrouped.append([lSequenceOfNum[start],lSequenceOfNum[x]])
            start = x+1

    else:
        lGrouped.append([lSequenceOfNum[start],lSequenceOfNum[x]])
print lGrouped
Run Code Online (Sandbox Code Playgroud)

这是我能做的最好的事情.是否有更"pythonic"的方式来做到这一点?谢谢..

Jef*_*ado 12

假设列表将始终按升序排列:

from itertools import groupby, count

numberlist = [1,2,3,4,5,8,9,10,11,200,201,202]

def as_range(g):
    l = list(g)
    return l[0], l[-1]

print [as_range(g) for _, g in groupby(numberlist, key=lambda n, c=count(): n-next(c))]
Run Code Online (Sandbox Code Playgroud)


Gar*_*tty 5

我意识到我已经使这个过程变得过于复杂了,与使用一个稍微复杂的生成器相比,手动计数要容易得多:

def ranges(seq):
    start, end = seq[0], seq[0]
    count = start
    for item in seq:
        if not count == item:
            yield start, end
            start, end = item, item
            count = item
        end = item
        count += 1
    yield start, end

print(list(ranges([1,2,3,4,5,8,9,10,11,200,201,202])))
Run Code Online (Sandbox Code Playgroud)

生产:

[(1, 5), (8, 11), (200, 202)]
Run Code Online (Sandbox Code Playgroud)

这个方法非常快:

此方法(和旧方法一样,它们几乎完全相同):

python -m timeit -s "from test import ranges" "ranges([1,2,3,4,5,8,9,10,11,200,201,202])"
1000000 loops, best of 3: 0.47 usec per loop
Run Code Online (Sandbox Code Playgroud)

杰夫·梅卡多(Jeff Mercado)的方法

python -m timeit -s "from test import as_range; from itertools import groupby, count" "[as_range(g) for _, g in groupby([1,2,3,4,5,8,9,10,11,200,201,202], key=lambda n, c=count(): n-next(c))]"
100000 loops, best of 3: 11.1 usec per loop
Run Code Online (Sandbox Code Playgroud)

速度快了20倍以上-尽管自然,除非速度重要,否则这不是真正的问题。


我以前使用生成器的解决方案:

import itertools

def resetable_counter(start):
    while True:
        for i in itertools.count(start):
            reset = yield i
            if reset:
                start = reset
                break

def ranges(seq):
    start, end = seq[0], seq[0]
    counter = resetable_counter(start)
    for count, item in zip(counter, seq): #In 2.x: itertools.izip(counter, seq)
        if not count == item:
            yield start, end
            start, end = item, item
            counter.send(item)
        end = item
    yield start, end

print(list(ranges([1,2,3,4,5,8,9,10,11,200,201,202])))
Run Code Online (Sandbox Code Playgroud)

生产:

[(1, 5), (8, 11), (200, 202)]
Run Code Online (Sandbox Code Playgroud)