如何将嵌套字典转换为defaultdict?

时间:2018-04-25 03:48:02

标签: python python-3.x

如何将嵌套字典转换为嵌套的defaultdict?

dic = {"a": {"aa": "xxx"}}
default = defaultdict(lambda: None, dic)
print(default["dummy_key"])  # return None
print(default["a"]["dummy_key"])  # KeyError

1 个答案:

答案 0 :(得分:6)

您需要循环或递归嵌套字典,通过其所有级别。

除非它可能非常深(如数百个级别),或者如此宽,以至于小的性能因素会有所不同,递归在这里可能是最简单的:

def defaultify(d):
    if not isinstance(d, dict):
        return d
    return defaultdict(lambda: None, {k: defaultify(v) for k, v in d.items()})

或者,如果您希望它与所有映射一起使用,而不仅仅是dicts,则可以在collections.abc.Mapping检查中使用dict代替isinstance

当然这假设你有一个纯粹的嵌套字典。如果您已经从一个典型的JSON响应中解析了一些内容,那里可能存在带有dict元素的列表值,那么您还必须处理其他可能性:

def defaultify(d):
    if isinstance(d, dict):
        return defaultdict(lambda: None, {k: defaultify(v) for k, v in d.items()})
    elif isinstance(d, list):
        return [defaultify(e) for e in d]
    else:
        return d

但是如果实际 来自JSON,那么在解析JSON时,将defaultdict用作object_pairs_hook可能会更好然后将其解析为dict,然后将其转换为defaultdict。

使用OrderedDict替代dict的文档中有一个示例,但这对我们来说不太有用 - 与OrderedDict和{dict不同{1}},defaultdict只能将一对迭代对作为唯一参数;它首先需要默认值工厂。所以我们可以使用functools.partial

将其绑定
d = json.loads(jsonstring, object_hook_pairs=partial(defaultdict, lambda: None))

等等。