复制复杂的字典结构

copy complex dictionary structure

假设你有一个字典的字典,但你想复制几乎整个结构(除了最里面的字典的值)。下面的代码可以做我想做的事,但我相信有更聪明的方法来做到这一点:

import sys

def main(argv=()):

    # original dictionary
    data = {1:{'l1': [1,2,3], 'l2': [2,1,6]}, 2: {'t1': ("w?",2), 't2': ("h!",4)}}

    # new values for the innermost keys
    newd = {'l1' : 1, 'l2' : 2, 't1' : 3, 't2' : 4}

    copy = dict.fromkeys(data.keys(), {})
    for k in copy.keys():
        copy[k] = dict.fromkeys(data[k].keys(), None)

    for k in copy.values():
        for e in k.keys():
            k[e] = newd[e]

    print(data)
    print(copy)

if __name__ == "__main__":
    sys.exit(main())

所以上面的代码打印:

{1: {'l2': [2, 1, 6], 'l1': [1, 2, 3]}, 2: {'t1': ('w?', 2), 't2': ('h!', 4)}}
{1: {'l2': 2, 'l1': 1}, 2: {'t1': 3, 't2': 4}}

这是我期望的结果,但是上面的代码似乎太冗长了。需要注意的是,在实际示例中,最内层键的值并不是那么简单,而是 numpy 数组,因此我不想对整个结构进行深度复制然后替换这些值。

您可以使用(假设您的代码中的 python 3):

>>> copy = {outer_key: {inner_key: newd.get(inner_key, inner_dict[inner_key]) for inner_key in inner_dict} for outer_key,inner_dict in data.items()}
>>> copy
{1: {'l1': 1, 'l2': 2}, 2: {'t1': 3, 't2': 4}}
>>> data
{1: {'l1': [1, 2, 3], 'l2': [2, 1, 6]}, 2: {'t1': ('w?', 2), 't2': ('h!', 4)}}

如果您 100% 确定每个键都在 newd 中,则可以将 newd.get(inner_key, inner_dict[inner_key]) 简化为 newd[inner_key]。或者 newd.get(inner_key) 如果您不在乎但丢失不在 newd.

中的值

使用复制模块:

import copy
data = {1:{'l1': [1,2,3], 'l2': [2,1,6]}, 2: {'t1': ("w?",2), 't2': ("h!",4)}}
cdata = copy.deepcopy(data)

然后您必须用新值修改副本中的最后一个字典。

深拷贝和浅拷贝见拷贝模块。

如果您要手动执行此操作以避免填充最后一层,递归是执行此操作的方法。

至少看看 copy 模块是如何做到的,并使用 dict.copy() 方法而不是使用 fromkeys() 构造新的字典。

使用循环来执行此操作将您限制为嵌套词典的确切数量。 如果你的字典有固定的形状,那么使用循环。

使用您自己的代码,您无需在任何地方调用 .keys,您可以在第一个循环中创建字典:

def main():

    # original dictionary
    data = {1:{'l1': [1,2,3], 'l2': [2,1,6]}, 2: {'t1': ("w?",2), 't2': ("h!",4)}}

    # new values for the innermost keys
    newd = {'l1' : 1, 'l2' : 2, 't1' : 3, 't2' : 4}

    copy = dict.fromkeys(data, {})
    for k in copy:
        copy[k] = {key:newd[key] for key in data[k]}