I have a use-case where I want to iterate from the middle of an array outwards, so I generate a list of indices as follows:
import itertools
def array_indices_from_middle(array_len: int, num_indices: int = 16) -> list[int]:
"""
Create indices for an array starting from the middle and then appending indices alternating the left and right.
If more indices are needed than the array length, start again from the middle.
"""
midpoint = (array_len - 1) // 2
sel_inds = []
left = range(midpoint - 1, -1, -1)
right = range(midpoint + 1, array_len, 1)
# right before left, because of how mid is chosen for even array lengths
alt = [i for i in itertools.chain.from_iterable(itertools.zip_longest(right, left)) if i is not None]
i = 0
while len(sel_inds) < num_indices:
if len(sel_inds) % array_len == 0:
sel_inds.append(midpoint)
else:
sel_inds.append(alt[i % len(alt)])
i += 1
return sel_inds
It passes the following unit tests:
assert array_indices_from_middle(array_len=5, num_indices=5) == [2, 3, 1, 4, 0]
assert array_indices_from_middle(array_len=5, num_indices=4) == [2, 3, 1, 4]
assert array_indices_from_middle(array_len=5, num_indices=8) == [2, 3, 1, 4, 0, 2, 3, 1]
assert array_indices_from_middle(array_len=6, num_indices=6) == [2, 3, 1, 4, 0, 5]
assert array_indices_from_middle(array_len=6, num_indices=5) == [2, 3, 1, 4, 0]
assert array_indices_from_middle(array_len=6, num_indices=9) == [2, 3, 1, 4, 0, 5, 2, 3, 1]
My combination of iterators feels a bit hacky. Is there a simpler way of approaching this problem? I'm not worried about corner cases.