2011-03-09 17 views
11

Tengo 5 diccionarios y deseo una unión de sus claves.python: ¿claves de unión de diccionario múltiple?

alldict = [dict1, dict2, dict3, dict4, dict5] 

me trataron

allkey = reduce(lambda x, y: set(x.keys()).union(y.keys()), alldict) 

pero me dio un error

AttributeError: 'set' object has no attribute 'keys' 

lo estoy haciendo mal? Estoy usando forloop normal, pero me pregunto por qué el código anterior no funcionó.

Respuesta

9

Su solución funciona para los dos primeros elementos de la lista, pero luego dict1 y dict2 quedó reducida en un conjunto y que se pone en juego su lambda como el x. Entonces, ahora x ya no tiene el método keys().

La solución es hacer que x sea un conjunto desde el principio al inicializar la reducción con un conjunto vacío (que pasa a ser el elemento neutro de la unión).

probar con un inicializador:

allkey = reduce(lambda x, y: x.union(y.keys()), alldict, set()) 

Una alternativa sin ningún lambdas sería:

allkey = reduce(set.union, map(set, map(dict.keys, alldict))) 
+0

Casi ... try set() como el inicializador – itsadok

+0

O: 'allkey = reduce (set.union, (set (d.keys()) para d en alldict))' – hughdbrown

1

Una estrategia simple para las neuronas no funcionales (juego de palabras):

allkey = [] 

for dictio in alldict: 
    for key in dictio: 
     allkey.append(key) 

allkey = set(allkey) 

Podemos convertir este código a un formulario de clasificación mucho utilizando conjuntos de comprensión:

allkey = {key for dictio in alldict for key in dictio} 

Este one-liner sigue siendo muy legible en comparación con el bucle for convencional. La clave para convertir un bucle anidado en una lista o establecer la comprensión es escribir el bucle interno (el que varía más rápido en el bucle anidado) como el último índice (es decir, for key in dictio).

+0

Si esto fuera una lista de comprensión, Yo lo hubiera votado. –

+0

@ BjörnPollex Tienes razón, la comprensión (del conjunto) compite con éxito con alternativas funcionales tanto en legibilidad como en concisión. – joaquin

0

Sólo una forma más, porque lo que el heno:

a={}; [ a.update(b) for b in alldict ] and a.keys() 

o ligeramente más misterioso

reduce(lambda a, b: a.update(b) or a, alldict, {}).keys() 

(estoy triste porque no hay ninguna función equivalente incorporada a

def f(a,b): 
    r = {} 
    r.update(a) 
    r.update(b) 
    return r 

está ahí?)

+0

Pruebe: 'def f (a, b): return dict (a.items() + b.items())' – hughdbrown

30

creo @chuck ya ha respondido la pregunta de por qué no funciona, pero una manera más sencilla de hacer esto sería recordar que el método union puede tomar varios argumentos:

allkey = set().union(*alldict) 

hace lo que quiere sin ningún tipo de bucles o lambdas.

0
set().union(dict1.keys(),dict2.keys()...) 

Probé la lista y no funcionó, así que simplemente lo puse aquí para cualquier persona.

Cuestiones relacionadas