The CPython documentation provides a selection of useful functions that are built on top of itertools. These have been made available in the adafruit_itertools_extras module. not only are these useful, but looking through the implementations is instructive on how iterators and the itertools functions can be used.

## `all_equal(iterable)`

Returns `True` if all the elements of `iterable` are equal to each other.

`>>> all_equal([6, 2*3, 12//2, 4+2])``True`
`>>> all_equal([6, 2*3, 12//2, 5, 4+2])``False`

## `dotproduct(vec1, vec2)`

Compute the dot product of two vectors. This is the sum of the products of pairs (one item from each vector)

`>>> dotproduct([1, 2, 3], [1, 2, 3])``14`

This is equivalent to (1 * 1) + (2 * 2) + (3 * 3) = 1 + 4 + 9 = 14

## `first_true(iterable, default=False, pred=None)`

Returns the first truthy value in `iterable`, i.e. the first value `x` for which `bool(x)` evaluates to `True`.

If no true value is found, returns `default`.

If `pred` is not `None`, returns the first item for which `pred(item)` is true.

`first_true([a,b,c], x)` is equivalent `a or b or c or x`
`first_true([a,b], x, f)` is equivalent `a if f(a) else b if f(b) else x`

## `flatten(iterable_of_iterables)`

Flatten one level of nesting.

`>>> list(flatten(['ABC', 'DEF']))``['A', 'B', 'C', 'D', 'E', 'F']`

`>>> list(flatten([[1, [2, 3]], [4, , 6]]))`
`[1, [2, 3], 4, , 6]`

## `grouper(iterable, n, fillvalue=None)`

Collect data from `iterable` into fixed-length chunks of size `n`. The final chunk will be filled in with `fillvalue` if iterable has less that a multiple of `n` elements.

`>>> list(grouper('ABCDEFG', 3, 'x'))`
`[('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')]`
`>>> list(grouper('ABCDEFG', 2))`
`[('A', 'B'), ('C', 'D'), ('E', 'F'), ('G', None)]`

## `iter_except(func, exception)`

Call `func` repeatedly until `exception` is raised, yielding the result of each call.

`>>> s = [1, 2, 3]`
`>>> s.pop()`
`3`
`>>> s.pop()`
`2`
`>>> s.pop()`
`1`
`>>> s.pop()`
`Traceback (most recent call last):`
`File "", line 1, in `
`IndexError: pop from empty list`

`>>> s = [1, 2, 3]`
`>>> list(iter_except(s.pop, IndexError))`
`[3, 2, 1]`

## `ncycles(iterable, n)`

Returns an iterable from `n` copies of the elements from `iterable`.

`>>> list(ncycles('ABC', 3))`
`['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C']`

## ` nth(iterable, n, default=None)`

Returns the `nth` (0-based) item of `iterable` or a `default` value (`None` by default) if `n` is out of range.

`>>> nth('ABCD', 0)`
`'A'`
`>>> nth('ABCD', 3)`
`'D'`
`>>> nth('ABCD', 4)`
`>>> nth('ABCD', 4, 'Z')`
`'Z'`

## `padnone(iterable)`

Returns the elements from `iterable` and then returns `None` indefinitely.

Useful for emulating the behavior of the built-in `map()` function.

`take(5, padnone([1, 2, 3]))` -> `1 2 3 None None`

## `pairwise(iterable)`

Pair up values in `iterable`.

`>>> list(pairwise(range(5)))`
`[(0, 1), (1, 2), (2, 3), (3, 4)]`

## `partition(predicate, iterable)`

Use `predicate` to partition entries in `iterable` into false entries and true entries.

`>>> t, f = partition(lambda x: x % 2, range(10))`
`>>> list(t)`
`[0, 2, 4, 6, 8]`
`>>> list(f)`
`[1, 3, 5, 7, 9]`

## `prepend(value, iterator)`

Prepend a `value` in front of `iterator`.

`prepend(1, [2, 3, 4])` -> `1 2 3 4`

## `quantify(iterable, predicate=bool)`

Count the number of elements in `iterable` for which `predicate` is `True`. By default it counts elements `x` where `bool(x)` results in `True`.

`>>> quantify([2, 56, 3, 10, 85], lambda x: x >= 10)`
`3`

## `repeatfunc(func, times=None, *args)`

Lazily repeat calls to `func` a number of times set by `times` with specified arguments (if any). If `times` is `None` (the default), call it infinitely. Return values from the function are generated by the resulting iterator.

`>>> take(5, repeatfunc(random.random))`
`[0.777482, 0.718999, 0.953034, 0.388373, 0.982035]`

## `roundrobin(*iterables)`

Return an iterable created by repeatedly picking a value from each of `iterables`, in order. As individual iterables are exhausted, they are dropped from the picking.

`>>> list(roundrobin('ABC', 'D', 'EF'))`
`['A', 'D', 'E', 'B', 'F', 'C']`

## `tabulate(function, start=0)`

Return an iterable populated by applying `function` to a sequence of consecutive integers, starting at `start` (defaults to 0).

`>>> take(5, tabulate(lambda x: x * x))`
`[0, 1, 4, 9, 16]`

## `tail(n, iterable)`

Return an iterator over the last `n` items of `iterable`. This only works if `iterable` is finite.

`>>> list(tail(3, 'ABCDEFG'))`
`['E', 'F', 'G']`

## `take(n, iterable)`

Return first `n` items of `iterable` as a list.

`>>> take(3, 'ABCDEF')`
`['A', 'B', 'C']`

This guide was first published on Mar 25, 2019. It was last updated on Mar 25, 2019.