Given this sorted array:
>>> x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
I want to slice up this array so that there are always 5 elements. 2 above and 2 below. I went with:
>>> [x[i-2:i+2] for i, v in enumerate(x)]
This results in:
[[], [], ['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], ['d', 'e', 'f', 'g'], ['e', 'f', 'g', 'h'], ['f', 'g', 'h', 'i'], ['g', 'h', 'i', 'j'], ['h', 'i', 'j', 'k'], ['i', 'j', 'k', 'l'], ['j', 'k', 'l']]
The problems with this are:
- There are 4 elements per group, not 5
- Not every group has 2 above and 2 below.
- The first and last groups are special cases. I do not want
blanks at the front. What I want to see is
['a', 'b', 'c', 'd', 'e']
as the first group and then['b', 'c', 'd', 'e', 'f']
as the second group.
I also played around with clamping the slices.
First I defined a clamp function like so:
>>> def clamp(n, smallest, largest): return max(smallest, min(n, largest))
Then, I applied the function like so:
>>> [x[clamp(i-2, 0, i):clamp(i+2, i, len(x))] for i, v in enumerate(x)]
But it didn't really work out so well:
[['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], ['d', 'e', 'f', 'g'], ['e', 'f', 'g', 'h'], ['f', 'g', 'h', 'i'], ['g', 'h', 'i', 'j'], ['h', 'i', 'j', 'k'], ['i', 'j', 'k', 'l'], ['j', 'k', 'l']]
Am I even barking up the right tree?
I found two SO articles about this issue, but they didn't address these edge cases:
Search a list for item(s)and return x number of surrounding items in python
efficient way to find several rows above and below a subset of data