| import random | |
| class RandomCycler: | |
| def __init__(self, source): | |
| if len(source) == 0: | |
| raise Exception("Can't create RandomCycler from an empty collection") | |
| self.all_items = list(source) | |
| self.next_items = [] | |
| def sample(self, count: int): | |
| shuffle = lambda l: random.sample(l, len(l)) | |
| out = [] | |
| while count > 0: | |
| if count >= len(self.all_items): | |
| out.extend(shuffle(list(self.all_items))) | |
| count -= len(self.all_items) | |
| continue | |
| n = min(count, len(self.next_items)) | |
| out.extend(self.next_items[:n]) | |
| count -= n | |
| self.next_items = self.next_items[n:] | |
| if len(self.next_items) == 0: | |
| self.next_items = shuffle(list(self.all_items)) | |
| return out | |
| def __next__(self): | |
| return self.sample(1)[0] |