[英]Pythonic: Find all consecutive sub-sequences of certain length
我有一個整數列表,我想在此列表中找到長度為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)]
這不是太可讀。 有任何可讀的pythonic方式可以做到這一點嗎?
這是更通用的解決方案,適用於任意輸入可迭代項(不僅是序列):
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
中的輸入。 它基於文檔中的示例,該示例顯示了如何查找連續數字 :
解決方案的關鍵是與enumerate()生成的范圍相區別,以便連續的整數都出現在同一組中(運行)。
itertools.tee
+ zip
允許以k方式迭代子字符串- 來自itertools
docs的pairwise
配方的一般化。
next(islice(iterator, n, n), None)
來自那里的consume
配方 。
例:
print(*consecutive_subseq([1,4,6,7,8,9], 3))
# -> (6, 7, 8) (7, 8, 9)
該代碼使用Python 3語法,如果需要,可以將其改編為Python 2。
一種解決方案如下:
import numpy # used diff function from numpy, but if not present, than some lambda or other helper function could be used.
def conseq_sequences(li, length):
return [int_list[i:i+length] for i in range(0, len(int_list)) if sum(numpy.diff(int_list[i:i+length]))==length-1]
基本上,首先,我從列表中獲取給定長度的連續子列表,然后檢查其元素之差的總和是否等於length - 1
。
請注意,如果元素是連續的,則它們的差之和將為length - 1
,例如,對於子列表[5,6,7]
,其元素的差為[1, 1]
,總和為2
。
但老實說,不確定此解決方案是否比您的解決方案更清晰或更pythonic。
萬一您沒有numpy
,可以輕松定義diff
函數,如下所示:
def diff(l):
'''For example, when l=[1,2,3] than return is [1,1]'''
return [x - l[i - 1] for i, x in enumerate(l)][1:]
使用operator.itemgetter和itertools.groupby
def conseq_sequences(li, length):
res = zip(*(li[i:] for i in xrange(length)))
final = []
for x in res:
for k, g in groupby(enumerate(x), lambda (i, x): i - x):
get_map = map(itemgetter(1), g)
if len(get_map) == length:
final.append(get_map)
return final
沒有進口。
def conseq_sequences(li, length):
res = zip(*(li[i:] for i in xrange(length)))
final = []
for ele in res:
if all(x == y+1 for x, y in zip(ele[1:], ele)):
final.append(ele)
return final
可以將其轉化為列表理解:
def conseq_sequences(li, length):
res = zip(*(li[i:] for i in xrange(length)))
return [ ele for ele in res if all(x == y+1 for x, y in zip(ele[1:], ele))]
def condition (tup):
if tup[0] + 1 == tup[1] and tup[1] + 1 == tup[2] :
return True
return False
def conseq_sequence(li):
return [x for x in map(None, iter(li), iter(li[1:]), iter(li[2:])) if condition(x)]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.