2015-04-06 74 views
0

我想知道是否有一種快速和pythonic的方式來創建基於字典的某些鍵字典?從拼合嵌套字典的映射創建一個新詞典

舉例來說,如果我有這個給定字典

{ 
    "a": "abc", 
    "b": {"b1": "1", "b2": "2", "b3": "3"}, 
    "c": 1, 
    "d": "timmy", 
    "e": "John" 
} 

我希望能夠創建一個新的字典,根據給定的字典中只有幾個鍵一對一的映射。所以在這個例子中,我想創建一個僅基於密鑰"b2""c""d"的字典。我也想給這些鍵一個不同的名字。所需的輸出將是:

{ 
    "out_b2": "2", 
    "out_c": 1, 
    "out_d": "timmy" 
} 

我能想出的最簡單的方法是創建嵌套的for循環執行此任務。我想知道是否有更高效的方法來實現這一目標。

我知道他的問題會根據投入和產出的情況而混淆不清。讓我們保持簡單,並說最深的級別是輸入的最大一個子詞典,並且輸出不會有任何偏差

+0

相當不清楚。你能舉一些更多的例子嗎?可以有更多的子目錄嗎? – 2015-04-06 08:57:17

+0

@tobias_k我想我能理解你爲什麼會感到困惑。我會馬上更新這個問題 – Liondancer 2015-04-06 09:06:39

+0

好吧,你不能避免不得不遞歸地扁平化所有嵌套的子類,除非你有一些啓發式的知道鍵'b2'位於'd ['b']子代碼中,或除非所有需要鍵恰好發現在頂層。是否有更多缺失的信息需要告訴我們?我們是否應該根據頂級密鑰的排名相似度來猜測接下來應該怎麼處理?這聽起來更加麻煩,而不僅僅是遞歸。 – smci 2015-04-06 09:10:23

回答

2

您可以遍歷字典項目,並檢查值是否爲dict再循環其項目和檢查重點是在你指定的鍵,然後將項目添加到新的詞典:

>>> old={ 
... "a": "abc", 
... "b": {"b1": "1", "b2": "2", "b3": "3"}, 
... "c": 1, 
... "d": "timmy", 
... "e": "John" 
... } 
>>> new={} 
>>> for i, j in old.items(): 
... if i in key: 
...  new['out_'+i]=j 
... elif isinstance(j,dict): 
...   for k, v in j.items(): 
...    if k in key: 
...     new['out_'+k]=v 
... 
>>> new 
{'out_d': 'timmy', 'out_b2': '2', 'out_c': 1} 
1

我會用另一種字典保存從舊名稱映射到所需的名稱:

mappings = { 
    'b.b2': 'out_b2', 
    'c': 'out_c', 
    'd': 'out_d', 
} 

這裏我我使用了.用於表示嵌套字典的子項 - 如果您的密鑰可能包含.,請使用不同的分隔符(例如/)。我會使用一個輔助函數來把那點分子項符號爲值:

def get_node(d, path): 
    if '.' not in path: 
     return d[path] 
    first, rest = path.split('.', 1) 
    return get_node(d[first], rest) 

然後得到自己想要的按鍵很簡單:

>>> old = { 
    "a": "abc", 
    "b": {"b1": "1", "b2": "2", "b3": "3"}, 
    "c": 1, 
    "d": "timmy", 
    "e": "John" 
} 
>>> {v: get_node(old, k) for k, v in mappings.iteritems()} 
{'out_b2': '2', 'out_c': 1, 'out_d': 'timmy'} 

我已經在使用的字典解析最後一部分 - 如果您的Python版本不支持該功能,則可以使用以下代碼:

dict((v, get_node(old, k)) for k, v in mappings.iteritems())