from typing import Union
from typing import Mapping
from typing import Any
from functools import reduce
import operator


def map_reduce(key_path: Union[str, list[str]],
               mapping: Mapping[str, Any]) -> Any:
    """Reduce a mapping, returning a value from an arbitrarily deep hierarcy.

    The result of calling this function is the same as successively
    subscripting each key in the `key_path`, starting from `mapping`.

    Parameters
    ----------
    key_path : str or list[str]
        A collection of sequential child keys into `mapping`. May be given as
        either a list of strings or a single string with dots (``.``)
        delimiting keys.
    mapping : Mapping[str, Any]
        The mapping to subscript.

    Example
    -------
    The following lines are equivalent:

        map_reduce('foo.bar.baz', things)
        # Is the same as:
        map_reduce(['foo', 'bar', 'baz'], things)
        # Is the same as:
        things['foo']['bar']['baz']
    """
    if isinstance(key_path, str):
        key_path = key_path.split('.')
    return reduce(operator.getitem, key_path, mapping)