2013-07-25 99 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]) 

結果也可以合併到不同的字典中。