hbutils.collection.functional

Functional utilities for nested collection processing.

This module provides function-oriented helpers for recursively transforming nested collection structures such as dictionaries, lists, and tuples. It is primarily focused on applying a callable to every leaf value in a nested structure while preserving the original container types and hierarchy.

The module exposes the following public functionality:

  • nested_map() - Apply a callable to all leaf values in a nested structure.

The implementation relies on hbutils.reflection.dynamic_call() to allow flexible call signatures for mapping functions, enabling callables that accept zero, one, or two positional parameters.

Example:

>>> from hbutils.collection.functional import nested_map
>>> nested_map(lambda x: x * 2, {'a': [1, 2], 'b': (3, {'c': 4})})
{'a': [2, 4], 'b': (6, {'c': 8})}
>>> nested_map(lambda x, p: (x, p), [10, {'k': 20}])
[(10, (0,)), {'k': (20, (1, 'k'))}]
>>> nested_map(lambda: 42, (1, 2, 3))
(42, 42, 42)

__all__

hbutils.collection.functional.__all__ = ['nested_map']

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

nested_map

hbutils.collection.functional.nested_map(f: Callable[[...], Any], s: Any) Any[source]

Map a callable over a nested structure.

This function recursively traverses a nested structure (containing lists, tuples, and dictionaries) and applies the given function to each leaf value. The callable can optionally accept the path to the current element as a parameter. Paths are represented as tuples of keys and indices.

The callable f is wrapped by hbutils.reflection.dynamic_call(), which allows it to accept flexible argument counts:

  • f() will be called with no arguments.

  • f(value) will be called with the leaf value.

  • f(value, path) will be called with the leaf value and its path.

Parameters:
  • f (Callable[..., Any]) – The function to apply to each leaf value.

  • s (Any) – The nested structure to map over. Supported containers are dictionaries, lists, and tuples. All other values are treated as leaf values.

Returns:

A new nested structure with the same container types and hierarchy as the input, with the function applied to all leaf values.

Return type:

Any

Example:

>>> from hbutils.collection.functional import nested_map
>>> nested_map(lambda x: x + 1, [
...     2, 3, (4, {'x': 2, 'y': 4}),
...     {'a': 3, 'b': (4, 5)},
... ])
[3, 4, (5, {'x': 3, 'y': 5}), {'a': 4, 'b': (5, 6)}]
>>> nested_map(lambda x, p: (x + 1) * len(p), [
...     2, 3, (4, {'x': 2, 'y': 4}),
...     {'a': 3, 'b': (4, 5)},
... ])
[3, 4, (10, {'x': 9, 'y': 15}), {'a': 8, 'b': (15, 18)}]
>>> nested_map(lambda: 233, [
...     2, 3, (4, {'x': 2, 'y': 4}),
...     {'a': 3, 'b': (4, 5)},
... ])
[233, 233, (233, {'x': 233, 'y': 233}), {'a': 233, 'b': (233, 233)}]