2

I wish to split a list into same-sized chunks using a "sliding window", but instead of truncating the list at the ends, I want to wrap around so that the final chunk can be spread across the beginning and end of the list.

For example, given a list:

l = [1, 2, 3, 4, 5, 6]

I wish to generate chunks of size n=3 as follows:

[1, 2, 3], [4, 5, 6]
[2, 3, 4], [5, 6, 1]
[3, 4, 5], [6, 1, 2]

Or the same list with chunks of size n=2 should be split as follows:

[1, 2], [3, 4], [5, 6]
[2, 3], [4, 5], [6, 1]

The list may not be divided evenly into n sublists (e.g. if the original list has length 7 and n=3 - or any value other than 7 or 1). The rounded value len(l) / n can be used to determine the split size, as in the usual case.

This post is related, although it does not wrap around as I need. I have tried but not managed anything useful. Any suggestions would be most welcome!

ongenz
  • 890
  • 1
  • 10
  • 20

1 Answers1

5

You can use itertools.islice over a wrap-around iterator generated from itertools.cycle:

from itertools import cycle, islice
def rolling_chunks(l, n):
    return ([list(islice(cycle(l), i + j, i + j + n)) for j in range(0, len(l), n)] for i in range(n))

so that list(rolling_chunks(l, 3)) returns:

[[[1, 2, 3], [4, 5, 6]], [[2, 3, 4], [5, 6, 1]], [[3, 4, 5], [6, 1, 2]]]

and that list(rolling_chunks(l, 2)) returns:

[[[1, 2], [3, 4], [5, 6]], [[2, 3], [4, 5], [6, 1]]]
blhsing
  • 91,368
  • 6
  • 71
  • 106