def unique_justseen(iterable, key=None): """Yields elements in order, ignoring serial duplicates >>> list(unique_justseen('AAAABBBCCDAABBB')) ['A', 'B', 'C', 'D', 'A', 'B'] >>> list(unique_justseen('ABBCcAD', str.lower)) ['A', 'B', 'C', 'A', 'D'] """ return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
def unique_to_each(*iterables): """Return the elements from each of the input iterables that aren't in the other input iterables. For example, suppose you have a set of packages, each with a set of dependencies:: {'pkg_1': {'A', 'B'}, 'pkg_2': {'B', 'C'}, 'pkg_3': {'B', 'D'}} If you remove one package, which dependencies can also be removed? If ``pkg_1`` is removed, then ``A`` is no longer necessary - it is not associated with ``pkg_2`` or ``pkg_3``. Similarly, ``C`` is only needed for ``pkg_2``, and ``D`` is only needed for ``pkg_3``:: >>> unique_to_each({'A', 'B'}, {'B', 'C'}, {'B', 'D'}) [['A'], ['C'], ['D']] If there are duplicates in one input iterable that aren't in the others they will be duplicated in the output. Input order is preserved:: >>> unique_to_each("mississippi", "missouri") [['p', 'p'], ['o', 'u', 'r']] It is assumed that the elements of each iterable are hashable. """ pool = [list(it) for it in iterables] counts = Counter(chain.from_iterable(map(set, pool))) uniques = {element for element in counts if counts[element] == 1} return [list(filter(uniques.__contains__, it)) for it in pool]
def groupby_transform(iterable, keyfunc=None, valuefunc=None): """Make an iterator that returns consecutive keys and groups from the *iterable*. *keyfunc* is a function used to compute a grouping key for each item. *valuefunc* is a function for transforming the items after grouping. *keyfunc* and *valuefunc* default to identity functions if they are not specified. When *valuefunc* is not specified, ``groupby_transform`` is the same as ``itertools.groupby()``. For example, to group a list of numbers by rounding down to the nearest 10, and then transform them into strings: >>> iterable = [0, 1, 12, 13, 23, 24] >>> keyfunc = lambda x: 10 * (x // 10) >>> valuefunc = lambda x: str(x) >>> grouper = groupby_transform(iterable, keyfunc, valuefunc) >>> [(k, list(g)) for k, g in grouper] [(0, ['0', '1']), (10, ['12', '13']), (20, ['23', '24'])] ``groupby_transform`` is useful when grouping elements of an iterable using a separate iterable as the key. To do this, ``zip()`` the iterables and pass a *keyfunc* that extracts the first element and a *valuefunc* that extracts the second element:: >>> from operator import itemgetter >>> keys = [0, 0, 1, 1, 1, 2, 2, 2, 3] >>> values = 'abcdefghi' >>> iterable = zip(keys, values) >>> grouper = groupby_transform(iterable, itemgetter(0), itemgetter(1)) >>> [(k, ''.join(g)) for k, g in grouper] [(0, 'ab'), (1, 'cde'), (2, 'fgh'), (3, 'i')] """ valuefunc = (lambda x: x) if valuefunc is None else valuefunc return ((k, map(valuefunc, g)) for k, g in groupby(iterable, keyfunc))
def dotproduct(vec1, vec2): """Returns the dot product of the two iterables >>> dotproduct([10, 10], [20, 20]) 400 """ return sum(map(operator.mul, vec1, vec2))
def quantify(iterable, pred=bool): """Return the how many times the predicate is true >>> quantify([True, False, True]) 2 """ return sum(map(pred, iterable))
def tabulate(function, start=0): """Return an iterator mapping the function over linear input. The start argument will be increased by 1 each time the iterator is called and fed into the function. >>> t = tabulate(lambda x: x**2, -3) >>> take(3, t) [9, 4, 1] """ return map(function, count(start))
def adjacent(predicate, iterable, distance=1): """Return an iterable over ``(bool, item)`` tuples where the ``item`` is drawn from *iterable* and the ``bool`` indicates whether that item satisfies the *predicate* or is adjacent to an item that does. For example, to find whether items are adjacent to a ``3``:: >>> list(adjacent(lambda x: x == 3, range(6))) [(False, 0), (False, 1), (True, 2), (True, 3), (True, 4), (False, 5)] Set *distance* to change what counts as adjacent. For example, to find whether items are two places away from a ``3``: >>> list(adjacent(lambda x: x == 3, range(6), distance=2)) [(False, 0), (True, 1), (True, 2), (True, 3), (True, 4), (True, 5)] This is useful for contextualizing the results of a search function. For example, a code comparison tool might want to identify lines that have changed, but also surrounding lines to give the viewer of the diff context. The predicate function will only be called once for each item in the iterable. See also ``groupby_transform()``, which can be used with this function to group ranges of items with the same ``bool`` value. """ # Allow distance=0 mainly for testing that it reproduces results with map() if distance < 0: raise ValueError('distance must be at least 0') i1, i2 = tee(iterable) padding = [False] * distance selected = chain(padding, map(predicate, i1), padding) adjacent_to_selected = map(any, windowed(selected, 2 * distance + 1)) return zip(adjacent_to_selected, i2)