Slicing windows of size N from a list at each step

Viewed 55

If I was to slice the following list, say with a step of 5, I could easily do:

l = list(range(20))
l[::5]

Giving:

[0, 5, 10, 15]

But what would be the easiest way to do the same but selecting centered windows of size 3 (or as many items as available) at each step? So:

[0, 1, 4, 5, 6, 9, 10, 11, 14, 15, 16]

For now I've bee trying something like:

[[l[i-1],l[i],l[i+1]] for i in l[::5][1:]]

Which is not even returning a flattened list.

1 Answers

Using list slicing inside a list comprehension:

[y for i in range(0, len(l), 5) for y in l[max(i-1, 0):i+2]]
# [0, 1, 4, 5, 6, 9, 10, 11, 14, 15, 16]

Generalizing, we have

window = 3 // 2
[y for i in range(0, len(l), 5) for y in l[max(i-window, 0):i+window+1]]
# [0, 1, 4, 5, 6, 9, 10, 11, 14, 15, 16]

Another option using itertools islice and chain:

from itertools import islice, chain

list(chain.from_iterable(
    islice(l, max(i-1, 0), i+2) for i in range(0, len(l), 5)))
# [0, 1, 4, 5, 6, 9, 10, 11, 14, 15, 16]
Related