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

Mai*_*awa 3 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
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 7

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

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

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

或者,如果您希望它与所有映射一起使用,而不仅仅是dicts,您可以使用collections.abc.Mapping而不是dictisinstance支票中.


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

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
Run Code Online (Sandbox Code Playgroud)

但是,如果这实际上从JSON来了,它可能会更好只使用你的defaultdict作为object_pairs_hook,而JSON被解析,而不是将其解析到一个字典,再后来将其转换为一个defaultdict.

在使用a OrderedDict代替的文档中有一个例子dict,但这对我们来说不太适用 - 不像,OrderedDict并且dict,defaultdict不能只将一对迭代的对作为其唯一的参数; 它首先需要默认值工厂.所以我们可以使用functools.partial以下方法将其绑定:

d = json.loads(jsonstring, object_hook_pairs=partial(defaultdict, lambda: None))
Run Code Online (Sandbox Code Playgroud)

等等.

  • 这工作完美,非常感谢!顺便说一下,我为你的最后一个例子提交了一个编辑,将 `object_hook_pairs` 更改为 `object_pairs_hook`,得到一个错误并发现了拼写错误。 (2认同)