#. -*- coding: utf-8 # # helper functions from copy import deepcopy import functools def dict_merge(target, *args): """ Recursively merges mutiple dicts """ # Merge multiple dicts if len(args) > 1: for obj in args: dict_merge(target, obj) return target # Recursively merge dicts and set non-dict values obj = args[0] if not isinstance(obj, dict): return obj for k, v in obj.items(): if k in target and isinstance(target[k], dict): dict_merge(target[k], v) else: target[k] = deepcopy(v) return target def get_rec(search_dict, field): """ Takes a dict with nested lists and dicts, and searches all dicts for a key of the field provided. """ fields_found = [] for key, value in search_dict.items(): if key == field: fields_found.append(value) elif isinstance(value, dict): results = get_rec(value, field) for result in results: fields_found.append(result) elif isinstance(value, list): for item in value: if isinstance(item, dict): more_results = get_recursively(item, field) for another_result in more_results: fields_found.append(another_result) return fields_found def gen_dict_extract(key, var): if hasattr(var,'iteritems'): for k, v in var.iteritems(): if k == key: yield v if isinstance(v, dict): for result in gen_dict_extract(key, v): yield result elif isinstance(v, list): for d in v: for result in gen_dict_extract(key, d): yield result def chained_get(dct, *keys): SENTRY = object() def getter(level, key): return 'NA' if level is SENTRY else level.get(key, SENTRY) return functools.reduce(getter, keys, dct)