【问题标题】:copy complex dictionary structure复制复杂的字典结构
【发布时间】:2015-11-08 02:59:52
【问题描述】:

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

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 dictionary copy deep-copy


    【解决方案1】:

    你可以使用(假设你的代码是 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 中的值。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        使用复制模块:

        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() 构造新的 dicts。

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

        【讨论】:

        • 抱歉,关于 numpy 数组的东西漏掉了。但是,我仍然告诉你该怎么做。去看看复制模块是如何做到的,然后编写类似的算法来满足你的规范。这就是我回答的精髓。此外,复制模块很灵活,您可以控制一些正在完成的复制,尤其是在使用您自己的对象时。
        猜你喜欢
        • 2017-04-06
        • 1970-01-01
        • 2017-02-14
        • 2011-10-20
        • 1970-01-01
        • 2011-12-07
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        相关资源
        最近更新 更多