我有一个整数列表,我想在这个列表中找到长度为n的所有连续子序列。例如:

>>> int_list = [1,4,6,7,8,9]
>>> conseq_sequences(int_list, length=3)
[[6,7,8], [7,8,9]]

我能想到的最好的办法是:
def conseq_sequences(self, li, length):
    return [li[n:n+length]
            for n in xrange(len(li)-length+1)
            if li[n:n+length] == range(li[n], li[n]+length)]

这不太可读有什么易读的蟒蛇式的方法吗?

最佳答案

下面是一个更通用的解决方案,适用于任意输入的iterable(不仅仅是序列):

from itertools import groupby, islice, tee
from operator import itemgetter

def consecutive_subseq(iterable, length):
    for _, consec_run in groupby(enumerate(iterable), lambda x: x[0] - x[1]):
        k_wise = tee(map(itemgetter(1), consec_run), length)
        for n, it in enumerate(k_wise):
            next(islice(it, n, n), None) # consume n items from it
        yield from zip(*k_wise)

itertools.groupby在输入中查找连续的子字符串,如6, 7, 8, 9它基于the example from the docs that shows how to find runs of consecutive numbers
解决方案的关键是使用
枚举(),使连续整数都出现在同一组中
(运行)。
itertools.tee+zip允许在子串k-wise上迭代——是pairwise recipe from the itertools docs的一个泛化。
next(islice(iterator, n, n), None)来自the consume recipe there
例子:
print(*consecutive_subseq([1,4,6,7,8,9], 3))
# -> (6, 7, 8) (7, 8, 9)

这段代码使用了Python 3语法,如果需要的话,可以根据Python 2进行调整。
另请参见,What is the most pythonic way to sort dates sequences?

10-08 04:14