合并嵌套字典(默认值)

时间:2012-03-16 01:30:27

标签: python

  

可能重复:
  python: Dictionaries of dictionaries merge

我将一堆应用程序设置存储在字典中,并以JSON格式保存到文本文件中。我想将它与一组默认的键/值合并,以便随着应用程序在将来发生变化,新的可以合并。例如:

defaults = { 
       'svn': "", 
       'notify': { 
          'email': "", 
          'notifo': { 'username': "", 'secret': ""},
          'active': False,
          'lastCheck': 0
       }
    }

local =  { 
       'svn': "/path/to/trunk/", 
       'notify': { 
          'email': "me@mysite.com", 
          'notifo': { 'username': "me", 'secret': "1234"},
       }
    }

请注意,'local'缺少['notify'] ['active']和['notify'] ['lastCheck']。我希望能够将两个词典合并为一个看起来像这样的词典:

local =  { 
       'svn': "/path/to/trunk/", 
       'notify': { 
          'email': "me@mysite.com", 
          'notifo': { 'username': "me", 'secret': "1234"},
          'active': False,
          'lastCheck': 0
       }
    }

我一直在寻找各处,但只看到人们压扁字典,合并第一级或用defaultdict做有趣的事情的例子。是否可以递归地合并嵌套的词典。

1 个答案:

答案 0 :(得分:4)

我认为以下函数可能会执行您想要的操作,但我没有检查每个字典中所有可能的缺失键组合。此外,这可能不适用于大型dicts:

import types 
def merge(x,y):
    # store a copy of x, but overwrite with y's values where applicable         
    merged = dict(x,**y)

    xkeys = x.keys()

    # if the value of merged[key] was overwritten with y[key]'s value           
    # then we need to put back any missing x[key] values                        
    for key in xkeys:
        # if this key is a dictionary, recurse                                  
        if type(x[key]) is types.DictType and y.has_key(key):
            merged[key] = merge(x[key],y[key])

    return merged

通过将合并函数和以下位放在文件test.py中,它似乎适用于您的示例,以及我为复杂性添加的一些额外项目:

defaults = {
       'svn': "",
       'notify': {
          'email': "",
          'notifo': { 'username': "", 'secret': ""},
          'active': False,
          'lastCheck': 0
       },
       'test': "another test"
    }

local =  {
       'svn': "/path/to/trunk/",
       'notify': {
          'email': "me@mysite.com",
          'notifo': { 'username': "me", 'secret': "1234", 'notx': 39},
       },
       'test2': 'again a test'
    }

print merge(defaults,local)

并且运行给出:

$ python test.py
{'svn': '/path/to/trunk/', 'test2': 'again a test', 'notify': {'lastCheck': 0, 'notifo': {'username': 'me', 'secret': '1234', 'notx': 39}, 'active': False, 'email': 'me@mysite.com'}, 'test': 'another test'}