Source code for warg.data_structures.mappings

from collections import defaultdict

import logging
from typing import Callable, Dict, Hashable, Iterable, Mapping, MutableMapping

_logger = logging.getLogger(__name__)
__all__ = [
    "invert_mapping",
    "invert_dict",
    "AppendingDict",
    "pivot_dict_object",
    "pivot_dict",
    "to_dict",
    "nested_dict",
]


def append_to_dict(d: Dict, key, value) -> Dict:
    """

    :param d:
    :type d:
    :param key:
    :type key:
    :param value:
    :type value:
    :return:
    :rtype:
    """
    d.setdefault(key, []).append(value)
    return d


[docs] class AppendingDict(Dict): # appending_dict = collections.defaultdict(list) def __setitem__(self, key, value): # self.setdefault(key, []).append(value) # append_to_dict(self, key, value) if key in self: self[key].append(value) else: super().__setitem__(key, [value])
def recurse_mapping(a: Mapping, call: Callable = print) -> None: for k, v in a.items(): if isinstance(v, Mapping): recurse_mapping(v) call(v)
[docs] def invert_mapping(m: Mapping) -> Mapping: # TODO: TEST THIS; MAY CONTAINS BUGS! """ Invert a mapping if a mapping does not have duplicate hashable values, then this is the same as invert_dict, otherwise values in new_m are tuples of keys with duplicate values :return: :rtype: """ if isinstance(m, MutableMapping): new_m = type(m)() else: new_m = {} for k, v in m.items(): if not isinstance(v, Hashable): raise TypeError(f"values must be hashable, was {type(v), v}, for key {k}") if v in new_m: if isinstance(new_m[v], Iterable) and (not isinstance(new_m[v], str)): new_m[v] = (*new_m[v], k) else: new_m[v] = [new_m[v], k] else: new_m[v] = k return new_m
[docs] def invert_dict(d: Mapping) -> Dict: # TODO: HANDLE DUPLICATE KEYS; CONVERT TO TUPLES """ Invert a dict :param d: :type d: :return: :rtype: """ return {v: k for k, v in d.items()}
[docs] def pivot_dict(d: Dict, key) -> Dict: # TODO: HANDLE DUPLICATE KEYS; CONVERT TO TUPLES """ pivot_key -> pivot_value :param d: :param key: :return: :rtype: """ return {v[key]: k for k, v in d.items()}
[docs] def pivot_dict_object(d: Dict, key) -> Dict: # TODO: HANDLE DUPLICATE KEYS; CONVERT TO TUPLES """ pivot_key -> pivot_value for object attributes :param d: :param key: :return: :rtype: """ return {getattr(v, key): k for k, v in d.items()}
[docs] def to_dict(m: Mapping) -> dict: o = {} for k, v in m.items(): if isinstance(v, Mapping): o[k] = to_dict(v) elif isinstance(v, str): o[k] = v elif isinstance(v, Iterable): o[k] = [to_dict(v_) if isinstance(v_, Mapping) else v_ for v_ in v] else: o[k] = v return o
nested_dict = lambda: defaultdict(nested_dict) if __name__ == "__main__": _logger.info(invert_mapping({"a": 1, "b": 2})) _logger.info(invert_mapping({"a": 2, "b": 2, "c": 3, "d": 4})) _logger.info(invert_dict({"a": 2, "b": 2, "c": 3, "d": 4})) def uhasdu(): from warg.data_structures.named_ordered_dictionary import NOD a = NOD({"b": NOD(c=1)}, d="usahfo7uyhaouw", f=[NOD(p="m")]) _logger.info(a) _logger.info(a.as_dict()) uhasdu() # logger.info(pivot_dict_object({"a": 2, "b": 2, "c": 3, "d": 4}, "id"))