2013-07-05 142 views
1

鑑於這兩類型的字典:修改的嵌套字典

empty = {'151': {'1': 'empty', '0': 'empty', '2': '2.30'}} 
full = {'151': {'1': 3.4, '0': 3.6, '2': 2}} 

首先,我要檢查,如果empty.keys() == full.keys()是否成立,我想從full字典替換相應的值empty值。它應該導致:

not_empty = {'151': {'1': '3.4', '0': '3.6', '2': '2.30'}} 

我到目前爲止的解決辦法:我想我會找出所有的按鍵與使用正則表達式empty值,但不管是什麼原因,我的代碼,到目前爲止,產生一個空字典{}

import re 
find_empty = re.findall("'(\d)':\s'empty'", str(empty))[0] 

if empty.keys() == full.keys(): 
    k = empty.values()[0].keys() 
    v = empty.values()[0].values() 
    print {k:v for k,v in empty.values()[0].iteritems()\ 
        if empty.values()[0][find_empty] != 'empty'} 

我希望它能輸出{'151': {'2': '2.30'}}是一個好的起點。無論如何,我想有更多的清理解決方案,然後使用正則表達式來完成這個任務,所以我們歡迎任何提示!

+0

是'151'始終是關鍵?是否會有多個關鍵? – Blender

+0

會有很多密鑰。 – nutship

回答

3

正則表達式不適合這份工作。我會建議像下面這樣的遞歸方法。

empty = {'151': {'1': 'empty', '0': 'empty', '2': '2.30'}} 
full = {'151': {'1': 3.4, '0': 3.6, '2': 2}} 

def repl(a, b): 
    clean = {} 
    for k, v in a.items(): 
     # This is the case where we want to replace what we have in b if we have something. Just in case, use the dict.get method and provide a default. 
     if v == 'empty': 
      clean[k] = b.get(k, 'Not there') 
     # If the value is another dict, then call this function with the value, and put the return as the value for our current key 
     elif isinstance(v, dict): 
      v_clean = repl(v, b.get(k, {})) 
      clean[k] = v_clean 
     # The value isn't equal to 'empty', and it isn't another dict, so just keep the current value. 
     else: 
      clean[k] = v 
    # Finally, return the cleaned up dictionary. 
    return clean 

print repl(empty, full) 

輸出

{'151': {'1': 3.4, '0': 3.6, '2': '2.30'}} 

編輯我不知道如果這需要所有的情況下照顧,但它可能是值得看看無妨。

empty = {'151': {'1': 'empty', '0': 'empty', '2': '2.30', '8': ['empty', 'empty', 5, {"foo2": "bar2", "1": "empty"}]}} 
full = {'151': {'1': 3.4, '0': 3.6, '2': 2, '8': ['foo', 'bar', 'baz', {"foo3": "bar3", "1": "2"}]}} 

def repl(a, b): 
    if isinstance(a, dict) and isinstance(b, dict): 
     clean = {} 
     for k, v in a.items(): 
      # This is the case where we want to replace what we have in b if we have something. Just in case, use the dict.get method and provide a default. 
      if v == 'empty': 
       clean[k] = b.get(k, 'Not there') 
      # If the value is another dict, then call this function with the value, and put the return as the value for our current key 
      elif isinstance(v, dict): 
       v_clean = repl(v, b.get(k, {})) 
       clean[k] = v_clean 
      # The value isn't equal to 'empty', and it isn't another dict, so just keep the current value. 
      elif isinstance(v, list): 
       v_clean = repl(v, b.get(k, [])) 
       clean[k] = v_clean 
      else: 
       clean[k] = v 
     # Finally, return the cleaned up dictionary. 
    elif isinstance(a, list) and isinstance(b, list): 
     clean = [] 
     for item_a, item_b in zip(a, b): 
      if item_a == 'empty': 
       clean.append(item_b) 
      elif isinstance(item_a, dict): 
       clean_a = repl(item_a, item_b) 
       clean.append(clean_a) 
      else: 
       clean.append(item_a) 
    return clean 

print repl(empty, full) 

輸出

{'151': {'1': 3.4, '0': 3.6, '2': '2.30', '8': ['foo', 'bar', 5, {'1': '2', 'foo2': 'bar2'}]}} 
+0

太棒了!謝謝:) – nutship

+0

如果你有一些時間,你能否通過添加一個解決方案來更新你的答案,就好像'空'和'全'是帶有列表值的字典?例如。 'empty = {'151':['empty','empty','2.30']}'替換的邏輯將是相同的。我不太瞭解你給我的解決方案,而且我恰好也需要它來處理列表。 – nutship

+0

@shipship:更新另一個例子來處理列表。 – sberry