2013-04-30 7 views
9

Mam następujący dict:Dodawanie do dict przy użyciu listy głównych ciągów jako ścieżka

aDict = { 
    "a" : { 
     "b" : { 
      "c1" : {}, 
      "c2" : {}, 
     } 
    } 
} 

drugi DICT:

aSecondDict = { 
    "d1" : {}, 
    "d2" : {}, 
    "d3" : {}, 
} 

i "ścieżka" krotka:

path = ("a", "b", "c2") 

Chcę teraz dodać drugi dyktat do pierwszego na ścieżce podanej przez krotkę:

aResultDict = { 
    "a" : { 
     "b" : { 
      "c1" : {}, 
      "c2" : { 
       "d1" : {}, 
       "d2" : {}, 
       "d3" : {}, 
      }, 
     } 
    } 
} 

Jaki jest sposób na osiągnięcie tego celu?

+1

mógłbyś naprawić słowniki – jamylak

+0

Thanks Martineau :) –

Odpowiedz

11

Można użyć reduce uzyskać słownika i dict.update umieścić nowych rzeczy tam:

reduce(lambda d,key: d[key],path,aDict).update(aSecondDict) 

Można nawet trochę bardziej mądry, jeśli chcesz:

reduce(dict.__getitem__,path,aDict).update(aSecondDict) 

Przypuszczam, że należy zauważyć, że te dwa podejścia są nieco inne. Ten ostatni wymusza, aby tylko zawierała więcej słowników (lub podklas dict), podczas gdy pierwsza pozwala na wszystko, co ma metodę __getitem__, aby być w aDict. As noted in the comments, można również użyć:

reduce(dict.get,path,aDict).update(aSecondDict) 

Jednak ta wersja będzie podnieść AttributeError jeśli starają się przechodzić do „link” w ścieżce, która jest nieistniejąca zamiast KeyError więc to nie podoba tyle samo. Ta metoda wymusza również, że każda wartość wzdłuż ścieżki jest podklasą dict lub dict.

reduce jest wbudowany dla python2.x. Zaczynając od python2.6, jest również dostępny jako functools.reduce. Kod, który chce być kompatybilny z python3.x powinny spróbować wykorzystać functools.reduce jak wbudowane usunięto python3.x

+0

lub 'zmniejszenia (dict.get, ścieżka, d) ' – jamylak

+0

@jamylak - Prawo. Inicjator zawsze działa jako ostatni. Dzięki. – mgilson

+1

Także jeśli OP chce kopii, może użyć 'copy.deepcopy', a następnie zrobić to – jamylak