#! /usr/bin/env python def window1(sequence, windowsize): """Pass a sliding window over a sequence. Iterates over a sequence/iterable, yielding consecutive slices of length windowsize from it, until the sequence is exhausted. Each slice will be a tuple. The last slice yielded will have the last element of the sequence as its last element: >>> list(window1(range(6), 3)) [(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5)] Note that if the sequence is shorter than the windowsize, no slices will be yielded: >>> list(window1(range(2), 3)) [] Typical use case is when you need peek ahead at the next element when iterating over a sequence (or peek behind at the previous element). """ buf = [] for item in sequence: buf.append(item) if len(buf) < windowsize: continue yield tuple(buf) del buf[0] return def window2(sequence, windowsize, filler): """Pass a sliding window over a sequence. Iterates over a sequence/iterable, yielding consecutive slices of length windowsize from it, until the sequence is exhausted. Each slice will be a tuple. When the end of the sequence is reached, the slices will be filled up at the end with filler, until the last element of the sequence is yielded as the first element of the yielded slice: >>> list(window2(range(5), 3, None)) [(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, None), (4, None, None)] If the sequence is shorter than the windowsize, even the first slice yielded will be filled out with the filler: >>> list(window2(range(2), 3, None)) [(0, 1, None), (1, None, None)] Typical use case is when you need peek ahead at the next element when iterating over a sequence. """ buf = [] for item in sequence: buf.append(item) if len(buf) < windowsize: continue yield tuple(buf) del buf[0] nleft = len(buf) buf += [filler] * (windowsize - nleft) for i in xrange(nleft): yield tuple(buf) del buf[0] buf.append(filler) return def window3(sequence, windowsize, filler): """Pass a sliding window over a sequence. Iterates over a sequence/iterable, yielding consecutive slices of length windowsize from it, until the sequence is exhausted. Each slice will be a tuple. The first few slices will be padded to the left with the filler element, so as to make them all windowsize long: >>> list(window2(range(5), 3, None)) [(None, None, 0), (None, 0, 1), (0, 1, 2), (1, 2, 3), (2, 3, 4)] If the sequence is shorter than the windowsize, even the last slice yielded will be filled out with the filler: >>> list(window2(range(2), 3, None)) [(None, None, 0), (None, 0, 1)] Typical use case is when you need peek behind at previous elements when iterating over a sequence. """ buf = [filler] * windowsize for item in sequence: del buf[0] buf.append(item) yield tuple(buf) return