复制复杂的字典结构

问题描述:

假设你有字典的字典,但你想复制几乎整个结构(除了最内层的字典的值)。下面的代码可以做我想做的,但我肯定有一个更聪明的方式来做到这一点:复制复杂的字典结构

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)}} 

可以简化newd.get(inner_key, inner_dict[inner_key])newd[inner_key],如果你是100%肯定,每一个按键都在newd。或者如果您不关心丢失不在newd中的值的问题,则返回newd.get(inner_key)

使用复印功能模块:

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

那么你就必须修改最后类型的字典与新值的副本。

查看复印模块进行深浅复印。

如果你打算用手来避免填充最后一层,那么递归就是这样做的方法。

了解复制模块至少如何执行它,并使用dict.copy()方法而不是使用fromkeys()构造新的字典。

使用循环来做到这一点,限制你确切数量的内置词典。 如果你的字典有固定的形状,然后使用循环。

+0

请阅读我的深度复制最后的意见。 – aaragon

+0

对不起,有关numpy数组滑落的内容。但是,我仍然告诉你该怎么做。去看看复制模块是如何做的,然后写出类似的算法,它会考虑你的规格。这是我的答案的精髓。另外,复制模块非常灵活,您可以控制一些正在进行的复制,特别是在使用自己的对象时。 – Dalen

使用自己的代码,你不需要任何地方调用.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]}