I have a list, e.g.
['a', 'b', 'c', ... 'z']
and I need to be able to repeatedly get a slice of fixed length, however, when the slice reaches the end it needs to continue as if the list was circular and loop back to the start, so that if the desired length was 3, one of the returned values would be ['z', 'a', 'b']
.
I have read a few questions concerning circular lists and itertools' itertools.cycle
(such as this one), however, none explain how to get a slice of said objects, and I tried but failed to get these to work.
My Code:
# a simplified version of my class
class MyClass:
def __init__(self):
self.all = list('abcdefghijklmnopqrstuvwxyz')
self.length = len(self.all)
self.range = slice(0, 3) # the starting slice
def update(self, delta):
# should also work when value of delta is negative
new_start = (self.range.start + delta) % self.length
new_stop = (self.range.stop + delta) % self.length
self.range = slice(new_start, new_stop)
# do things with self.visible...
@property
def visible(self):
return self.all[self.range]
instance = MyClass()
for i in range(27):
print(instance.visible)
instance.update(1)
(Python 3.7)
Output:
['a', 'b', 'c']
['b', 'c', 'd']
... # 20 lines, expected results
['w', 'x', 'y']
[] # wanted ['x', 'y', 'z']
[] # wanted ['y', 'z', 'a']
[] # wanted ['z', 'a', 'b']
['a', 'b', 'c']
The problem with the above code is that once self.range.stop
reaches self.length
, it becomes smaller than self.range.start
and then nothing is returned until self.range.start
also reaches self.length
and self.range.stop
is no longer smaller.
How can this be fixed to allow for the slice (or, if required, multiple slices) to return the correct section of the list, even when this means values from both the start and end?