from typing import List
from typing import Dict
from typing import Any
from typing import Callable
from functools import reduce


def pluck(
    keys: List[str],
    items: List[Dict[str, Any]],
    key_sep: str = ".",
    key_func: Callable[[str], str] = lambda k: k,
) -> List[Dict[str, Any]]:
    """Pluck `keys` from `items`. Nested keys can be specified by concatenating with
    `key_sep` (i.e. `key1.key2`). Returned keys are set via `key_func`."""
    return [
        {
            key_func(k): reduce(
                lambda d, k: d[k] if isinstance(d, dict) else getattr(d, k), k.split(key_sep), d
            )
            for k in keys
        }
        for d in items
    ]