Пример #1
0
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)))
Пример #2
0
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)))
Пример #3
0
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]
Пример #4
0
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))
Пример #5
0
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]
Пример #6
0
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))
Пример #7
0
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))
Пример #8
0
def quantify(iterable, pred=bool):
    """Return the how many times the predicate is true

        >>> quantify([True, False, True])
        2

    """
    return sum(map(pred, iterable))
Пример #9
0
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))
Пример #10
0
def quantify(iterable, pred=bool):
    """Return the how many times the predicate is true

        >>> quantify([True, False, True])
        2

    """
    return sum(map(pred, iterable))
Пример #11
0
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))
Пример #12
0
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))
Пример #13
0
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)
Пример #14
0
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)