def windowed(seq, n, fillvalue=None, step=1): """Return a sliding window of width *n* over the given iterable. >>> all_windows = windowed([1, 2, 3, 4, 5], 3) >>> list(all_windows) [(1, 2, 3), (2, 3, 4), (3, 4, 5)] When the window is larger than the iterable, ``fillvalue`` is used in place of missing values:: >>> list(windowed([1, 2, 3], 4)) [(1, 2, 3, None)] Each window will advance in increments of *step*:: >>> list(windowed([1, 2, 3, 4, 5, 6], 3, fillvalue='!', step=2)) [(1, 2, 3), (3, 4, 5), (5, 6, '!')] """ if n < 0: raise ValueError('n must be >= 0') if n == 0: yield tuple() return if step < 1: raise ValueError('step must be >= 1') it = iter(seq) window = deque([], n) append = window.append # Initial deque fill for _ in range(n): append(next(it, fillvalue)) yield tuple(window) # Appending new items to the right causes old items to fall off the left i = 0 for item in it: append(item) i = (i + 1) % step if i % step == 0: yield tuple(window) # If there are items from the iterable in the window, pad with the given # value and emit them. if (i % step) and (step - i < n): for _ in range(step - i): append(fillvalue) yield tuple(window)
def padded(iterable, fillvalue=None, n=None, next_multiple=False): """Yield the elements from *iterable*, followed by *fillvalue*, such that at least *n* items are emitted. >>> list(padded([1, 2, 3], '?', 5)) [1, 2, 3, '?', '?'] If *next_multiple* is ``True``, *fillvalue* will be emitted until the number of items emitted is a multiple of *n*:: >>> list(padded([1, 2, 3, 4], n=3, next_multiple=True)) [1, 2, 3, 4, None, None] If *n* is ``None``, *fillvalue* will be emitted indefinitely. """ it = iter(iterable) if n is None: for item in chain(it, repeat(fillvalue)): yield item elif n < 1: raise ValueError('n must be at least 1') else: item_count = 0 for item in it: yield item item_count += 1 remaining = (n - item_count) % n if next_multiple else n - item_count for _ in range(remaining): yield fillvalue
def powerset(iterable): """Yields all possible subsets of the iterable >>> list(powerset([1,2,3])) [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] """ s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
def powerset(iterable): """Yields all possible subsets of the iterable >>> list(powerset([1,2,3])) [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] """ s = list(iterable) return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
def random_combination_with_replacement(iterable, r): """Returns a random combination of length r, chosen with replacement. >>> random_combination_with_replacement(range(3), 5) # # doctest:+SKIP (0, 0, 1, 2, 2) """ pool = tuple(iterable) n = len(pool) indices = sorted(randrange(n) for i in range(r)) return tuple(pool[i] for i in indices)
def random_combination(iterable, r): """Returns a random combination of length r, chosen without replacement. >>> random_combination(range(5), 3) # doctest:+SKIP (2, 3, 4) """ pool = tuple(iterable) n = len(pool) indices = sorted(sample(range(n), r)) return tuple(pool[i] for i in indices)
def count_cycle(iterable, n=None): """Cycle through the items from *iterable* up to *n* times, yielding the number of completed cycles along with each item. If *n* is omitted the process repeats indefinitely. >>> list(count_cycle('AB', 3)) [(0, 'A'), (0, 'B'), (1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')] """ iterable = tuple(iterable) if not iterable: return iter(()) counter = count() if n is None else range(n) return ((i, item) for i in counter for item in iterable)
def divide(n, iterable): """Divide the elements from *iterable* into *n* parts, maintaining order. >>> group_1, group_2 = divide(2, [1, 2, 3, 4, 5, 6]) >>> list(group_1) [1, 2, 3] >>> list(group_2) [4, 5, 6] If the length of the iterable is not evenly divisible by n, then the length of the smaller iterables will not be identical:: >>> children = divide(3, [1, 2, 3, 4, 5, 6, 7]) >>> [list(c) for c in children] [[1, 2, 3], [4, 5], [6, 7]] If the length of the iterable is smaller than n, then the last returned iterables will be empty: >>> children = divide(5, [1, 2, 3]) >>> [list(c) for c in children] [[1], [2], [3], [], []] This function will exhaust the iterable before returning and may require significant storage. If order is not important, see ``distribute()``, which does not first pull the iterable into memory. """ if n < 1: raise ValueError('n must be at least 1') seq = tuple(iterable) q, r = divmod(len(seq), n) ret = [] for i in range(n): start = (i * q) + (i if i < r else r) stop = ((i + 1) * q) + (i + 1 if i + 1 < r else r) ret.append(iter(seq[start:stop])) return ret