Skip to content

Reference

nested

nested(contents: Container)

A Collection which supports recursive versions of in, len and offers a recursive count and index.

ATTRIBUTE DESCRIPTION
contents

the original nested content

TYPE: Any

Examples:

>>> numberlists = [[1, 2], [3, 4], [5, 6], [[7, 8], 9]]
>>> nest = nested(numberlists)

>>> nest.contents
[[1, 2], [3, 4], [5, 6], [[7, 8], 9]]

>>> 5 in nest
True

>>> 10 in nest
False

>>> len(nest)
9

>>> [x for x in nest]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list(nest)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> nest.count(5)
1
Source code in recurtools/nested.py
44
45
46
def __init__(self, contents: Container) -> None:
    """Initialise a nested container."""
    self.contents = contents

count

count(x: Any) -> int

Return the number of times x occurs within the nested structure.

Examples:

>>> nest = nested([1, 2, [3, 2]])
>>> nest.count(2)
2
>>> nest.count(4)
0
>>> nest = nested(["ab", "b", ["c", "db", ["e","bob"]]])
>>> nest.count("b")
5
Source code in recurtools/nested.py
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def count(self, x: Any) -> int:
    """
    Return the number of times x occurs within the nested structure.

    Examples:
        ```
        >>> nest = nested([1, 2, [3, 2]])
        >>> nest.count(2)
        2
        >>> nest.count(4)
        0
        ```

        ```
        >>> nest = nested(["ab", "b", ["c", "db", ["e","bob"]]])
        >>> nest.count("b")
        5
        ```
    """
    return list(flatten(self.contents, preserve=None)).count(x)

index

index(x: Any) -> tuple[int]

Return zero-based index in the nested structure of the first item whose value is equal to x.

Index is of the form a tuple with index at each level of the hierarchy. Raises a ValueError if there is no such item.

Examples:

>>> nest = nested([1, 2, [3, 2]])
>>> nest.index(2)
(1,)
>>> nest.index(3)
(2, 0)
>>> nest.index(4)
Traceback (most recent call last):
...
ValueError: 4 is not in nest
>>> nest = nested(["Foo",[1,"Bar"]])
>>> nest.index("a")
(1, 1, 1)
Source code in recurtools/nested.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def index(self, x: Any) -> tuple[int]:
    """
    Return zero-based index in the nested structure of the first item whose value is equal to x. 

    Index is of the form a tuple with index at each level of the hierarchy.
    Raises a ValueError if there is no such item.

    Examples:
        ```
        >>> nest = nested([1, 2, [3, 2]])
        >>> nest.index(2)
        (1,)
        >>> nest.index(3)
        (2, 0)
        >>> nest.index(4)
        Traceback (most recent call last):
        ...
        ValueError: 4 is not in nest
        ```

        ```
        >>> nest = nested(["Foo",[1,"Bar"]])
        >>> nest.index("a")
        (1, 1, 1)
        ```
    """

    class NotFoundError(LookupError):
        pass
    class NoIndexError(LookupError):
        pass

    def _indexrecursive(seq, val):  # noqa: ANN001
        try:
            return (seq.index(val),)
        except AttributeError as a: # seq does not support index()
            raise NoIndexError from a
        except ValueError as v: # seq does support index() but val not found
            for i, s in enumerate(seq):
                if s is not seq:  # single char strings etc.
                    with suppress(NotFoundError, NoIndexError):
                        return tuple(flatten((i, _indexrecursive(s, val))))
            raise NotFoundError from v
    try:
        return _indexrecursive(self.contents, x)
    except NotFoundError:
        raise ValueError (f"{x} is not in nest") from None  # noqa: EM102, TRY003

flatten

flatten(
    nestediterable: Iterable,
    *,
    preserve: type | Iterable[type] | None = stringlike
) -> Generator

Recursively flattens a nested iterable and returns all elements in order left to right.

PARAMETER DESCRIPTION
nestediterable

The nested iterable to flatten

TYPE: Iterable

PARAMETER DESCRIPTION
preserve

Optional type(s) which will not be flattened. Default: (str, bytes).
If you want to flatten strings then use preserve=None.

TYPE: type | Iterable[type]

bytes

bytes are flattened into individual int codes, unless preserve includes bytes. See PEP467 for more background

Examples:

>>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [x for x in flatten([1,2,"abc",[3,4]], preserve = None)]
[1, 2, 'a', 'b', 'c', 3, 4]
>>> [x for x in flatten([1,2,"abc",[3,4]])]
[1, 2, 'abc', 3, 4]
Source code in recurtools/utils.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def flatten(nestediterable: Iterable, *, preserve: type | Iterable[type] | None = stringlike) -> Generator:
    """
    Recursively flattens a nested iterable and returns all elements in order left to right.

    Args:
        nestediterable (Iterable): The nested iterable to flatten

    Keyword Args:
        preserve (type | Iterable[type]): Optional type(s) which will not be flattened. Default: `(str, bytes)`.  
            If you want to flatten strings then use `preserve=None`.


    !!! Note "bytes"
        `bytes` are flattened into individual `int` codes, unless `preserve` includes `bytes`.
        See [PEP467](https://peps.python.org/pep-0467/) for more background

    Examples:
        ```
        >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
        [1, 2, 3, 4, 5, 6, 7, 8, 9]
        ```

        ```
        >>> [x for x in flatten([1,2,"abc",[3,4]], preserve = None)]
        [1, 2, 'a', 'b', 'c', 3, 4]
        ```

        ```
        >>> [x for x in flatten([1,2,"abc",[3,4]])]
        [1, 2, 'abc', 3, 4]
        ```
    """
    try:
        iter(nestediterable)
    except TypeError:
        yield nestediterable
    else:
        if preserve and isinstance(nestediterable, preserve):
            yield nestediterable
        else:
            for item in nestediterable:
                if item is nestediterable:  # catch e.g. a single char string
                    yield item
                else:
                    yield from flatten(item, preserve=preserve)