2013-07-25 72 views
1

比如我有两个类型的字典:如何合并在python中追加两个嵌套字典?

schema = { 
    'type': 'object', 
    'properties': { 
     'reseller_name': { 
      'type': 'string', 
     }, 
     'timestamp': { 
      'type': 'integer', 
     }, 
    }, 
    'required': ['reseller_name', 'timestamp'], 
} 

schema_add = { 
    'properties': { 
     'user_login': { 
      'type': 'string', 
     }, 
    }, 
    'required': ['user_login'], 
} 

我怎样才能得到下一个与附加结果字典合并:

schema_result = { 
    'type': 'object', 
    'properties': { 
     'reseller_name': { 
      'type': 'string', 
     }, 
     'timestamp': { 
      'type': 'integer', 
     }, 
     'user_login': { 
      'type': 'string', 
     }, 
    }, 
    'required': ['reseller_name', 'timestamp', 'user_login'], 
} 

规则:

相同的路径propertiesrequired对于0123例如和scheme_add

  1. 如果这两个字典都具有相同路径的字典,则它们使用相同的规则进行合并。
  2. 如果这两个字典都有相同路径的列表,则添加第一个第二个列表。
  3. 如果两个字典都具有相同路径的简单值(或字典和非字典或列表和非列表),则第一个值用第二个值覆盖。
  4. 如果只有一个字典有一些路径的关键,比设置这个键和值。
+0

你似乎已经回答了你自己的问题。你列出的规则*就是你的答案。你在实施时遇到了什么困难?如果是这样,你有什么确切的问题? –

+0

在我列出规则之前,这看起来很困难。现在用@ Nicolas78帮我做。 – tbicr

回答

2

不知道问题出在哪里,但是写下来的方式几乎就像一个电脑程序,这个例子就像一个测试用例。你为什么不从这个开始?

def add_dict(d1, d2): 
    newdict = {} 
    for (key, value) in d1.iteritems(): 
     if key in d2: ... 
      #apply rules, add to newdict, use 
     else: 
      #simply add 
    for (key, value) in d2.iteritems(): 
     if not key in d1: 
      # simply add 
    return newdict 

这可能会写的更紧,但可能更容易编辑。

编辑..写最后的评论后,忍不住写一个更好的实现

def merge_values(a,b): 
    if a==None or b==None: 
     return a or b 
    # now handle cases where both have values 
    if type(a)==dict: 
     return add_dict(a, b) 
    if type(a)==list: 
     ... 

def add_dict(d1,d2): 
    return dict(
     [ 
      (key, 
      merge_values(
       d1.get(key,None), 
       d2.get(key,None))) 
      for key 
      in set(d1.keys()).union(d2.keys()) 
     ]) 
2

我自己的解决方案@ Nicolas78帮助:

def merge(obj_1, obj_2): 
    if type(obj_1) == dict and type(obj_2) == dict: 
     result = {} 
     for key, value in obj_1.iteritems(): 
      if key not in obj_2: 
       result[key] = value 
      else: 
       result[key] = merge(value, obj_2[key]) 
     for key, value in obj_2.iteritems(): 
      if key not in obj_1: 
       result[key] = value 
     return result 
    if type(obj_1) == list and type(obj_2) == list: 
     return obj_1 + obj_2 
    return obj_2 
+2

如果你设置了'result = dict(obj_2)',那么你可以删除整个第二个循环。 – RussW

+1

'result = obj_2.copy()'更快 – tbicr

+0

啊,我只注意到现在你是提问者。 – RussW

2

我加入简单解决这个问题。假设样本数据不会改变。

def merge_nested_dicts(schema,schema_add): 
    new_schema = schema 
    for k in schema: 
     if k in schema_add.keys(): 
      if isinstance(schema_add[k],dict): 
       new_schema[k].update(schema_add[k]) 
      if isinstance(schema_add[k],list): 
       new_schema[k] = new_schema[k]+schema_add[k] 
    return new_schema 
0

如果您完全了解按键,请尝试此操作。

schema['properties'].update(schema_add['properties']) 
schema['result'].append(schema_add['result']) 

结果在模式中合并。

如果您完全不知道密钥,那么需要一个循环来查找内部列表和字典。

for value in schema: 
    if value is dict: 
     if schema_add.has_key(value) and schema_add[value] is dict: 
      schema[value].update(schema_add[value]) 
    elif value is list: 
     if schema_add.has_key(value) and schema_add[value] is list: 
      schema[value].append(schema_add[value]) 

结果也可以合并到不同的字典中。