a2m.itertools

a2m.itertools is a collection of functions and classes implementing some convenient iteration recipes.

Todo

Write module-level documentation part.

Functions and classes

a2m.itertools.even(thing)

Filter all even elements of a sequence.

Parameters:thing – an arbitrary iterable
Return type:itertools.islice() iterator
Returns:iterator over all even elements of given sequence

This function is just a wrapper over itertools.islice(). Indexes are 1-based.

Example:

>>> it = even('abcdef')
>>> it
<itertools.islice object at 0x...>
>>> list(it)
['b', 'd', 'f']
a2m.itertools.odd(thing)

Filter all odd elements of a sequence.

Parameters:thing – an arbitrary iterable
Return type:itertools.islice() iterator
Returns:iterator over all odd elements of given sequence

This function is just a wrapper over itertools.islice(). Indexes are 1-based.

Example:

>>> it = odd('abcdef')
>>> it
<itertools.islice object at 0x...>
>>> list(it)
['a', 'c', 'e']
a2m.itertools.every_nth(thing, n, shift=0)

Takes an iterable and returns every n-th element from beginning, optionally shifted by shift

This funcion is just a handy wrapper over itertools.islice(). Indexes are 1-based.

Parameters:
  • thing – an arbitrary iterable
  • n (int) – enumerator defining sequence step
  • shift (int) – pattern cycling shift (negative values are accepted)

Example:

>>> it = every_nth(range(20), 3)
>>> it
<itertools.islice object at 0x...>
>>> list(it)
[2, 5, 8, 11, 14, 17]

Another example, with non-zero shift:

>>> it = every_nth(range(20), 3, 2)
>>> it
<itertools.islice object at 0x...>
>>> list(it)
[1, 4, 7, 10, 13, 16, 19]
>>> list(every_nth(range(20), 4, -1))
[2, 6, 10, 14, 18]
a2m.itertools.flatten(thing, protected_iterables=(), enforce_scalar=None)

Takes an iterable of nested iterables and scalars and traverses it into a flat sequence.

Parameters:
  • thing – a nested iterable of arbitrary depth,
  • protected_iterables – a list of types which should be treated as scalars unconditionally,
  • enforce_scalar (callable or None) – a callable that takes single argument and defines if its value should be protected from flattenting. Provides more flexible way to protect values on instance level.
Return type:

generator iterator

Returns:

a flat sequence of all elements from source iterable.

Here are some examples. Flatten everything:

>>> seq = [(1, 2), [3, (4,), 5, 5.5], 6, [7, 8]]
>>> list(flatten(seq))
[1, 2, 3, 4, 5, 5.5, 6, 7, 8]

Flatten everything but tuples:

>>> seq = [(1, 2), [3, (4,), 5, 5.5], 6, [7, 8]]
>>> list(flatten(seq, protected_iterables=(tuple,)))
[(1, 2), 3, (4,), 5, 5.5, 6, 7, 8]

Flatten, but protect sequences shorter than 3 elements:

>>> seq = [(1, 2), [3, (4,), 5, 5.5], 6, [7, 8]]
>>> protect_short = lambda s: hasattr(s, '__iter__') and len(tuple(s)) < 3
>>> list(flatten(seq, enforce_scalar=protect_short))
[(1, 2), 3, (4,), 5, 5.5, 6, [7, 8]]

Note: Strings are always protected. If you wants to flatten a nested iterable of strings into single one, follow this example:

>>> lst = list(flatten(['a', ['sequence', ['of'], 'strings']]))
>>> lst
['a', 'sequence', 'of', 'strings']
>>> ''.join(lst)
'asequenceofstrings'

And if a character-wise iterator is required, this recipe can be used:

>>> import itertools
>>> it = itertools.chain(*flatten(['a', ['sequence', ['of'], 'strings']]))
>>> it
<itertools.chain object at 0x...>
>>> list(it)
['a', 's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 'o', 'f', 's', 't', 'r', 'i', 'n', 'g', 's']