deepflatten¶
- class iteration_utilities.deepflatten(iterable, depth=-1, types=None, ignore=None)¶
Flatten an iterable with given depth.
- Parameters:
- iterableiterable
Any iterable to flatten.
- depth
int
or None, optional Flatten depth levels of nesting or all if
depth=-1
. Default is-1
.Note
If the depth is known this significantly speeds up the function!
- typestype, tuple of types, optional
Which types should be flattened. If not given it flattens all items if
iter(item)
does not throw aTypeError
.Note
If the types are given this significantly speeds up the function but only if the depth is unknown.
- ignoretype, iterable of types or None, optional
The types which should not be flattened. If not given all types are flattened.
- Returns:
- flattened_iterablegenerator
The iterable with the depth level of nesting flattened.
Examples
To flatten a given depth:
>>> from iteration_utilities import deepflatten >>> list(deepflatten([1, [1,2], [[1,2]], [[[1,2]]]], depth=1)) [1, 1, 2, [1, 2], [[1, 2]]]
To completely flatten it:
>>> list(deepflatten([1, [1,2], [[1,2]], [[[1,2]]]])) [1, 1, 2, 1, 2, 1, 2]
To ignore for example dictionaries:
>>> # Only the keys of a dictionary will be kept with deepflatten. >>> list(deepflatten([1, 2, [1,2], {1: 10, 2: 10}])) [1, 2, 1, 2, 1, 2] >>> list(deepflatten([1, 2, [1,2], {1: 10, 2: 10}], ignore=dict)) [1, 2, 1, 2, {1: 10, 2: 10}]
In this case we could have also chosen only to flatten the lists:
>>> list(deepflatten([1, 2, [1,2], {1: 10, 2: 10}], types=list)) [1, 2, 1, 2, {1: 10, 2: 10}]
Warning
If the iterable contains recursive iterable objects (i.e. UserString) one either needs to set
ignore
or a depth that is notNone
. Otherwise this will raise anRecursionError
(orRuntimeError
on older Python versions) because each item in aUserString
is itself aUserString
, even if it has a length of 1! The builtin strings (str
,bytes
,unicode
) are special cased, but only the exact types because subtypes might implement custom not-recursive__iter__
methods. This means that these won’t run into the infinite recursion, but subclasses might.See for example:
>>> from collections import UserString >>> list(deepflatten([1, 2, [1,2], UserString('abc')], depth=1)) [1, 2, 1, 2, 'a', 'b', 'c'] >>> list(deepflatten([1, 2, [1,2], UserString('abc')], ignore=UserString)) [1, 2, 1, 2, 'abc']
This function is roughly (it’s missing some of the complicated details and performance optimizations of the actual function) equivalent to this python function:
def deepflatten(iterable, depth=None, types=None, ignore=None): if depth is None: depth = float('inf') if depth == -1: yield iterable else: for x in iterable: if ignore is not None and isinstance(x, ignore): yield x if types is None: try: iter(x) except TypeError: yield x else: yield from deepflatten(x, depth - 1, types, ignore) elif not isinstance(x, types): yield x else: yield from deepflatten(x, depth - 1, types, ignore)