Consider some given sequence and a window length, say the list
a = [13 * i + 1 for i in range(24)]
(so that
In [61]: a
Out[61]:
[1,
14,
27,
40,
...,
287,
300]
)
and window length 3.
I'd like to take the sliding window sum of this sequence, but cyclically; i.e., to calculate the length-24 list
:
[sum([1, 14, 27]),
sum([14, 27, 40]),
...,
sum([287, 300, 1]),
sum([300, 1, 14])]
The best I could come up with, using collections.deque
and Stupid Lambda Tricks, was
d = collections.deque(range(24))
d.rotate(1)
map(lambda _: d.rotate(-1) or sum(a[i] for i in list(d)[: 3]), range(24))
Is there something less horrible?
What about the simple
a = [13 * i + 1 for i in range(24)]
w = 3
aa = a + a[:w]
print([sum(aa[i:i+w]) for i in range(len(a))])
Note that if the window is big there are better ways to compute a sliding window sum in O(n)
(i.e. with a constant time per element, independently of the size of the window).
The idea is to do a "scan conversion" replacing each element with the sum of all elements from the start (this requires single pass).
After that the sum of elements from x0 to x1 is then computed in O(1) with
sum_table[x1] - sum_table[x0]
In code:
sum_table = [0]
for v in a:
sum_table.append(sum_table[-1] + v)
for v in a[:w]:
sum_table.append(sum_table[-1] + v)
print([sum_table[i+w] - sum_table[i] for i in range(len(a))])