2010-11-20 20 views
6

Tengo varios diccionarios con claves diferentes y comunes, más claves diferentes y comunes en el diccionario anidado. A continuación se muestra un ejemplo simplificado, los diccionarios reales tienen miles de claves.¿Combinar diccionarios anidados, por claves anidadas?

{1:{"Title":"Chrome","Author":"Google","URL":"http://"}} 
{1:{"Title":"Chrome","Author":"Google","Version":"7.0.577.0"}} 
{2:{"Title":"Python","Version":"2.5"}} 

Lo que me gustaría fusionar en un solo diccionario.

{1:{"Title":"Chrome","Author":"Google","URL":"http://","Version":"7.0.577.0"}, 
2:{"Title":"Python","Version":"2.5"}} 

puedo iterar sobre ambos diccionarios, comparar claves y update los diccionarios anidados, pero es probable que haya una manera más eficiente, o Pythonic, manera de hacer esto. Si no, ¿cuál es el más eficiente?

No es necesario comparar los valores del diccionario anidado.

+0

Si realmente el mapeo de teclas enteros secuenciales, no tendría más sentido producir una lista como salida? –

+0

Mucha discusión y consejos aquí también: http://stackoverflow.com/questions/38987/how-can-i-merge-two-python-dictionaries-as-a-single-expression – mjhm

+0

Parece muy poco realista que cada uno de los "varios diccionarios" tienen exactamente un par de clave/valor: hace que uno se pregunte por qué son diccionarios cuando una simple tupla o lista con dos elementos podría funcionar igual de bien. – martineau

Respuesta

5
from collections import defaultdict 

mydicts = [ 
    {1:{"Title":"Chrome","Author":"Google","URL":"http://"}}, 
    {1:{"Title":"Chrome","Author":"Google","Version":"7.0.577.0"}}, 
    {2:{"Title":"Python","Version":"2.5"}}, 
] 

result = defaultdict(dict) 

for d in mydicts: 
    for k, v in d.iteritems(): 
     result[k].update(v) 

print result 

defaultdict(<type 'dict'>, 
    {1: {'Version': '7.0.577.0', 'Title': 'Chrome', 
     'URL': 'http://', 'Author': 'Google'}, 
    2: {'Version': '2.5', 'Title': 'Python'}}) 
+0

Modificación secundaria: el segundo 'for' podría reemplazarse por' k, v = next (d.iteritems()) 'y la siguiente línea se dedented. En realidad, no hay mucha diferencia, pero se vería * más rápido. ;-) – martineau

+0

@martineau: también parece menos útil: 'next()' solo funciona en python 2.6+. También la forma en que escribí acepta más de una clave en cada 'dict', o' dict' vacía sin ahogarse o hacer lo incorrecto – nosklo

+0

Bueno, estás en lo cierto con 'next()' no disponible antes de v2.6 - - Al escribirlo, olvidé que OP quería una solución compatible con v2.5. Sin embargo, es discutible si sería deseable aceptar '' dict's anidados mal formados con más de una clave y, por último, 'next()' puede manejar 'dict's vacíos sin ningún problema. Considerando todo, sigo creyendo que mi comentario es una observación válida para aquellos que usan al menos v2.6 de Python. – martineau

2

de su ejemplo, parece que se puede hacer algo como:

from collections import defaultdict 
mydict = defaultdict(dict) 
for indict in listofdicts: 
    k, v = indict.popitem() 
    mydict[k].update(v) 
Cuestiones relacionadas