Skip to content

Instantly share code, notes, and snippets.

@erip
Created November 14, 2022 22:25
Show Gist options
  • Save erip/1585c78e63d90c16954f0c8d878702af to your computer and use it in GitHub Desktop.
Save erip/1585c78e63d90c16954f0c8d878702af to your computer and use it in GitHub Desktop.
A silly circular buffer-style map-style iterator
#!/usr/bin/env python3
from typing import Iterator
from itertools import cycle, islice, chain
class GetItemIterator(Iterator):
def __init__(self, *it):
self._len, it_copy = self._get_len(it)
self._it = cycle(it_copy)
self._curr_idx = 0
self._curr_data = next(self._it)
@staticmethod
def _get_len(it):
len_ = 0
it_copy = ()
for i in it:
it_copy = chain(it_copy, (i,))
len_ += 1
return len_, it_copy
def __getitem__(self, i):
if i == self._curr_idx:
return self._curr_data
elif i > self._curr_idx:
self._curr_data = next(islice(self._it, i - self._curr_idx))
self._curr_idx = i
return self._curr_data
else:
# need to roll over
self._curr_data = next(islice(self,_it, (self._curr_idx + i) % self._len))
self._curr_idx = (self._curr_idx + i) % self._len
return self._curr_data
def __len__(self):
return self._len
def __next__(self):
self._curr_idx = 0 if self._curr_idx - 1 == self._len else self._curr_idx + 1
return next(self._it)
if __name__ == "__main__":
it = GetItemIterator(1,2,3, 4)
for i in range(10):
print(i, it[i])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment