如何处理不是分组大小倍数的序列上的滑动 window 值?

How to handle a sliding window of values over sequences that aren't multiples of the grouping size?

我有一个列表,我想使用滑动 window 方法将我的列表分组为三个元素的元组。

根据我的循环中设置的参数,一旦 i 到达最后两个元素,三元组将被截断,因为列表末尾没有更多值。

我需要的是在达到该点后使用起始值。请查看屏幕截图,因为它可能会更好地显示我的问题。

test = [(1,2), (3,4), (5,6), (7,8)]

for i in range(len(test)):
    print(test[i : i+3])

输出为:

[(1, 2), (3, 4), (5, 6)]
[(3, 4), (5, 6), (7, 8)]
[(5, 6), (7, 8)]
[(7, 8)]

但是,我需要它来做:

[(1, 2), (3, 4), (5, 6)]
[(3, 4), (5, 6), (7, 8)]
[(5, 6), (7, 8), (1, 2)]
[(7, 8), (1, 2), (2, 3)]

然后将其展平使其最终看起来像:

[((1, 2), (3, 4), (5, 6))
 ((3, 4), (5, 6), (7, 8))
 ((5, 6), (7, 8), (1, 2))
 ((7, 8), (1, 2), (2, 3))]

Screenshot of output for better clarity

有什么方法可以做到这一点?

可能有优化以下内容的方法,但一种方法是使用 operator.itemgetter() 并为每个 window 子组创建适当的索引集。

from operator import itemgetter
from pprint import pprint


test = [(1,2), (3,4), (5,6), (7,8)]

window_size = 3
length = len(test)
result = []
for i in range(len(test)):
    indices = (x%length for x in range(i, i+window_size))
    result.append(itemgetter(*indices)(test))

pprint(result)

输出:

[((1, 2), (3, 4), (5, 6)),
 ((3, 4), (5, 6), (7, 8)),
 ((5, 6), (7, 8), (1, 2)),
 ((7, 8), (1, 2), (3, 4))]

接受的答案很好,但我会提供(我认为是)更简单的方法:

test = [(1,2), (3,4), (5,6), (7,8)]

win_size = 3
groups = []

for i in range(len(test)):
        groups.append((test[i:] + test[:i])[:win_size])

print(groups)

输出:

[[(1, 2), (3, 4), (5, 6)],
 [(3, 4), (5, 6), (7, 8)],
 [(5, 6), (7, 8), (1, 2)],
 [(7, 8), (1, 2), (3, 4)]]

每次通过循环,我们都会重新排列 test 以使其处于所需的顺序,然后通过按 window 大小切片来创建每个组。

尽管我认为它的可读性较差,但您也可以使用列表推导式:

groups = [(test[i:] + test[:i])[:win_size] for i in range(len(test))]

如果组必须是元组而不是列表,请最初将 test 定义为元组,或酌情使用 tuple(test[i:] + test[:i])