2012-04-22 27 views
6

Necesitaba comparar 2 diccionarios para encontrar el conjunto de claves en un diccionario que no estaba en el otro.¿Manera concisa de encontrar la diferencia "clave" entre 2 diccionarios?

sé que Python establece objetos apoyan:

set3=set1-set2 

pero no puedo hacer:

dict3=dict1-dict2 

o:

missingKeys=dict1.keys()-dict2.keys() 

(Me sorprendió un poco en el último punto, porque en Java las claves son un objeto Set). Una solución es:

missingKeys=set(dict1.keys())-set(dict2.keys()) 

¿Hay alguna forma mejor o más concisa para hacer esto?

+0

creo que la última línea está suficientemente concisa a mí mismo, pero ... Creo que una pregunta más interesante es "¿Cómo eliminar todo z en Y de X?" donde X e Y son listas. Esto sería útil cuando existan z duplicados en X que aparezcan en Y deberían quedar solos, por ejemplo. –

+0

@pst: Bueno, se siente un poco extraño crear objetos establecidos, solo para aprovechar la función de diferencia() ... –

+0

Por otro lado, como * es * un conjunto, puede aprovechar un mejor O ... para las diferencias de listas usando la comprensión es fácil, pero un poco más prolijo. Sin embargo, el mismo rendimiento si la lista "probada" se convierte en un "conjunto". –

Respuesta

3

Tal

[x for x in dict1.keys() if x not in dict2.keys()] 
+2

Creo que esto podría ser incluso un poco más conciso: '[x para x en dict1.keys() si x no en dict2]' ya que '' en dict.keys() 'es lo mismo que' x in dict' – mgilson

+0

@mgilson: mientras señale que 'x in dict' es lo mismo que' x en dict.keys() ', entonces la reducción completa es' [x para x en dict1 si x no en dict2] '. –

+1

@SamGoldberg Estás en lo correcto.La razón por la que no pensé en esto es porque 'for x in dict' llama al método' __iter__' en un dict, mientras que 'if x in dict' llama al método' __contains__'. Entonces, en este caso, el 'en 'hace dos cosas diferentes, simplemente tienen el mismo resultado. De todos modos: '[x para x en dict1 si x no en dict2] 'es más conciso como usted señaló. – mgilson

15

Python 2.7:

>>> d = {1:2, 2:3, 3:4} 
>>> d2 = {2:20, 3:30} 
>>> set(d)-set(d2) 
set([1]) 

Python 3.2:

>>> d = {1:2, 2:3, 3:4} 
>>> d2 = {2:20, 3:30} 
>>> d.keys()-d2.keys() 
{1} 
+0

+1 ¡Oh, furtivo Python 3.x! –

+0

¿Está diciendo que el método dict.keys() de Python 3.2 devuelve un conjunto (como Java)? ¿Alguna razón por la cual la versión anterior no hizo eso? –

+2

@SamGoldberg: no, en realidad devuelve un objeto dict_keys, no un conjunto, pero tiene muchas operaciones de conjunto. Ver, p. [esta pregunta] (http://stackoverflow.com/questions/7296716/what-is-dict-keys-dict-items-and-dict-values). – DSM

4

Para manera portátil de hacerlo se recomienda usar dict.viewkeys en Python 2.7 - es es backport de Python 3.x dict.keys y se convierte automáticamente por 2to3.

Ejemplo:

>>> left = {1: 2, 2: 3, 3: 4} 
>>> right = {2: 20, 3:30} 
>>> left.viewkeys() - right.viewkeys() 
set([1]) 
1

Esto debería funcionar en Python 2.7 y 3.x:

>>> keys = getattr(dict, 'viewkeys', dict.keys) 
>>> left = {1: 2, 2: 3, 3: 4} 
>>> right = {2: 20, 3:30} 
>>> list(keys(left) - keys(right)) 
[1] 
Cuestiones relacionadas