2015-10-04 47 views
8

我有一個深刻的任意組嵌套詞典:的Python:應用函數值在嵌套的字典

x = {'a': 1, 'b': {'c': 6, 'd': 7, 'g': {'h': 3, 'i': 9}}, 'e': {'f': 3}} 

和我想的功能主要適用於在字典的所有整數,所以喜歡map ,我想,但對於嵌套字典。

因此:map_nested_dicts(x, lambda v: v + 7)將是那種目標。

我被困在最好的方式來存儲密鑰層,然後把修改後的值放回到正確的位置。

這樣做的最佳方法是什麼?

+0

遞歸解決方案mig高工作。迭代項目,如果一個值是一個整數,改變它,如果該值是一個字典,傳遞它在一個遞歸調用。 – wwii

回答

13

訪問所有嵌套值遞歸:

import collections 

def map_nested_dicts(ob, func): 
    if isinstance(ob, collections.Mapping): 
     return {k: map_nested_dicts(v, func) for k, v in ob.iteritems()} 
    else: 
     return func(ob) 

map_nested_dicts(x, lambda v: v + 7) 
# Creates a new dict object: 
# {'a': 8, 'b': {'c': 13, 'g': {'h': 10, 'i': 16}, 'd': 14}, 'e': {'f': 10}} 

在某些情況下,它需要修改原來字典對象(以避免重新創建它):

import collections 

def map_nested_dicts_modify(ob, func): 
    for k, v in ob.iteritems(): 
     if isinstance(v, collections.Mapping): 
      map_nested_dicts_modify(v, func) 
     else: 
      ob[k] = func(v) 

map_nested_dicts_modify(x, lambda v: v + 7) 
# x is now 
# {'a': 8, 'b': {'c': 13, 'g': {'h': 10, 'i': 16}, 'd': 14}, 'e': {'f': 10}} 

如果你使用Python 3:

+0

我想知道第一個函數中的'''items'''方法是否會造成麻煩,但它看起來像只有映射或映射派生物使用這種方法 - 任何想法? – wwii

+0

@wwii這是某種鴨子打字......是的,它可以用於'dict','dict'子類,'ChainMap'和更多的映射類型。 – vaultah

+0

@wwii但你可能是對的,我用'isinstance(ob,collections.Mapping)'替換'try..except'塊。 – vaultah

1

只是爲了擴大vaultah的回答,如果你的元素之一可以是替換列表collections.Mapping,並且希望以處理這些:

import collections 

def map_nested_dicts_modify(ob, func): 
for k, v in ob.iteritems(): 
    if isinstance(v, collections.Mapping): 
     map_nested_dicts_modify(v, func) 
    elif isinstance(v, list): 
     ob[k] = map(func, v) 
    else: 
     ob[k] = func(v)