Python 列表的滑动窗口

at.*_*at. 8 python list dataframe python-3.x pandas

有没有一种有效或优雅的方法来检索Python中列表的所有k大小子列表?例如:

arr = [2, 3, 5, 7, 11, 13]
Run Code Online (Sandbox Code Playgroud)

我想要所有 3 元素子列表:

result = [[2, 3, 5],
          [3, 5, 7],
          [5, 7, 11],
          [7, 11, 13]]
Run Code Online (Sandbox Code Playgroud)

我知道我可以用 for 循环创建这个,用 切片列表arr[i:i+3],但我正在处理的列表是巨大的,我希望有一个有效的机制,或者至少是一个优雅的或 Pythonic 的机制。

我也在使用 Pandas,很高兴使用 Pandas 机制。

Mat*_*ipp 9

如果您确实想构建列表,我认为您不会比像这样的基本列表理解做得更好:

arr = [2, 3, 5, 7, 11, 13]
result = [arr[i:i+k] for i in range(len(arr)-k+1)]
Run Code Online (Sandbox Code Playgroud)

如果你想最小化内存使用,你可以使用生成器:

arr = [2, 3, 5, 7, 11, 13]
def window(arr, k):
    for i in range(len(arr)-k+1):
        yield arr[i:i+k]

for group in window(arr, 3):
    ...  # do something with group
Run Code Online (Sandbox Code Playgroud)

您还可以做一些事情,将列表的副本zip放在一起,每个副本偏移一。k但这将占用与第一个解决方案一样多的内存,并且可能没有太多性能优势。

numpy 或 pandas 中可能有一些快速有效的东西,但您需要更多地展示您的输入和输出应该是什么样子。

这里还有一些其他的想法,但它们专注于一般的迭代(您只能将项目取出一次),而不是列表(您可以通过索引访问项目,可能会重复访问)。


Pyg*_*irl 7

您可以使用more_itertools

import more_itertools
list(more_itertools.windowed(arr,3))
Run Code Online (Sandbox Code Playgroud)
[(2, 3, 5), (3, 5, 7), (5, 7, 11), (7, 11, 13)]
Run Code Online (Sandbox Code Playgroud)

或者

使用itertools

from itertools import islice

def pairwise(iterable, n):
    "s -> (s0,s1,..s(n-1)), (s1,s2,.., sn), (s2, s3,..,s(n+1)), ..."
    iters = iter(iterable)
    result = tuple(islice(iters, n))
    if len(result) == n:
        yield result
    for elem in iters:
        result = result[1:] + (elem,)
        yield result
Run Code Online (Sandbox Code Playgroud)


jez*_*ael 6

您可以使用步幅

arr = [2, 3, 5, 7, 11, 13]

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

a = rolling_window(np.array(arr), 3)
print (a)
[[ 2  3  5]
 [ 3  5  7]
 [ 5  7 11]
 [ 7 11 13]]


print (a.tolist())
[[2, 3, 5], 
 [3, 5, 7], 
 [5, 7, 11], 
 [7, 11, 13]]
Run Code Online (Sandbox Code Playgroud)