2013-04-30 7 views
9

Ich habe folgendes dict:zu einer dict eine Liste von Schlüsselketten als Pfad

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

ein zweites dict:

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

und ein "Pfad" Tupel:

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

Ich möchte jetzt das zweite dict zum ersten an dem vom Tupel bereitgestellten Pfad hinzufügen:

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

Was ist der pythonische Weg, dies zu erreichen?

+1

Könnten Sie bitte Ihre Wörterbücher – jamylak

+0

Dank martineau fix :) –

Antwort

11

Sie reduce verwenden können das Wörterbuch zu bekommen und dict.update die neuen Sachen setzen dort in:

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

Sie können sogar ein wenig klüger erhalten, wenn Sie wollen:

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

Ich nehme an, es sollte angemerkt werden, dass die beiden Ansätze leicht unterschiedlich sind. Letztere zwingt aDict, nur mehr Wörterbücher (oder dict Unterklassen) zu enthalten, während erstere alles erlaubt, was eine __getitem__-Methode in aDict hat. As noted in the comments, könnten Sie auch:

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

Doch diese Version wird ein AttributeError erhöhen, wenn Sie versuchen, einen „Link“ auf dem Weg zu durchqueren, die nicht vorhanden ist eher als ein KeyError, so dass ich es nicht mag genauso viel. Diese Methode erzwingt auch, dass jeder Wert entlang des Pfades eine dict oder dict Unterklasse ist.

reduce ist eine integrierte für python2.x. Ab python2.6 ist es auch als functools.reduce verfügbar. Code, der mit python3.x kompatibel sein will, sollte versuchen, functools.reduce zu verwenden, da die eingebaute in python3.x entfernt

+0

oder 'reduzieren (dict.get, Pfad, d) ' – jamylak

+0

@jamylak - Richtig. Der Initialisierer geht immer zuletzt. Vielen Dank. – mgilson

+1

Auch wenn OP eine Kopie möchte, kann er 'copy.deepcopy' verwenden und dann – jamylak

Verwandte Themen