¿Extraer subconjunto de pares clave-valor del objeto del diccionario de Python?

Tengo un objeto de diccionario grande que tiene varios pares de valores clave (alrededor de 16), pero solo estoy interesado en 3 de ellos. ¿Cuál es la mejor manera (más corta / eficiente / más elegante) para lograrlo?

Lo mejor que sé es:

bigdict = {'a':1,'b':2,....,'z':26} subdict = {'l':bigdict['l'], 'm':bigdict['m'], 'n':bigdict['n']} 

Estoy seguro de que hay una manera más elegante que esta. Ideas?

Tu podrías intentar:

 dict((k, bigdict[k]) for k in ('l', 'm', 'n')) 

… o en Python 3 Versiones de Python 2.7 o posteriores (gracias a Fábio Diniz por señalar que también funciona en 2.7) :

 {k: bigdict[k] for k in ('l', 'm', 'n')} 

Actualización: como señala Håvard S , supongo que usted sabe que las claves estarán en el diccionario; vea su respuesta si no puede hacer esa suposición. Alternativamente, como lo señala el timbo en los comentarios, si desea que una clave que falta en bigdict a None , puede hacer:

 {k: bigdict.get(k, None) for k in ('l', 'm', 'n')} 

Si está usando Python 3, y solo quiere que las claves en el nuevo dict que existen en la original, puede usar el hecho de que los objetos de vista implementan algunas operaciones de configuración:

 {k: bigdict[k] for k in bigdict.keys() & {'l', 'm', 'n'}} 

Un poco más corto, al menos:

 wanted_keys = ['l', 'm', 'n'] # The keys you want dict((k, bigdict[k]) for k in wanted_keys if k in bigdict) 
 interesting_keys = ('l', 'm', 'n') subdict = {x: bigdict[x] for x in interesting_keys if x in bigdict} 

Un poco de comparación de velocidad para todos los métodos mencionados:

 Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Jan 29 2016, 14:26:21) [MSC v.1500 64 bit (AMD64)] on win32 In[2]: import numpy.random as nprnd keys = nprnd.randint(1000, size=10000) bigdict = dict([(_, nprnd.rand()) for _ in range(1000)]) %timeit {key:bigdict[key] for key in keys} %timeit dict((key, bigdict[key]) for key in keys) %timeit dict(map(lambda k: (k, bigdict[k]), keys)) %timeit dict(filter(lambda i:i[0] in keys, bigdict.items())) %timeit {key:value for key, value in bigdict.items() if key in keys} 100 loops, best of 3: 3.09 ms per loop 100 loops, best of 3: 3.72 ms per loop 100 loops, best of 3: 6.63 ms per loop 10 loops, best of 3: 20.3 ms per loop 100 loops, best of 3: 20.6 ms per loop 

Como era de esperar: las comprensiones de diccionario son la mejor opción.

Esta respuesta utiliza una comprensión del diccionario similar a la respuesta seleccionada, pero no lo hará excepto en un elemento faltante.

Versión de Python 2:

 {k:v for k, v in bigDict.iteritems() if k in ('l', 'm', 'n')} 

Versión de Python 3:

 {k:v for k, v in bigDict.items() if k in ('l', 'm', 'n')} 

Tal vez:

 subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n']]) 

Python 3 incluso admite lo siguiente:

 subdict={a:bigdict[a] for a in ['l','m','n']} 

Tenga en cuenta que puede verificar la existencia en el diccionario de la siguiente manera:

 subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n'] if x in bigdict]) 

resp. para python 3

 subdict={a:bigdict[a] for a in ['l','m','n'] if a in bigdict} 

También puedes usar el mapa (que es una función muy útil para conocer de todos modos):

sd = dict(map(lambda k: (k, l.get(k, None)), l))

Ejemplo:

large_dictionary = {'a1':123, 'a2':45, 'a3':344} list_of_keys = ['a1', 'a3'] small_dictionary = dict(map(lambda key: (key, large_dictionary.get(key, None)), list_of_keys))

PD. Tomé prestado el .get (clave, Ninguno) de una respuesta anterior 🙂

Bueno, esto es algo que me ha molestado varias veces, así que gracias Jayesh por preguntarlo.

Las respuestas anteriores parecen ser una solución tan buena como cualquier otra, pero si está utilizando todo este código, tiene sentido envolver la funcionalidad en mi humilde opinión. Además, hay dos posibles casos de uso aquí: uno en el que te preocupa si todas las palabras clave están en el diccionario original. y uno donde no lo haces. Sería bueno tratar a ambos por igual.

Así que, para mi valor de dos peniques, sugiero escribir una subclase de diccionario, por ejemplo

 class my_dict(dict): def subdict(self, keywords, fragile=False): d = {} for k in keywords: try: d[k] = self[k] except KeyError: if fragile: raise return d 

Ahora puedes sacar un sub-diccionario con

 orig_dict.subdict(keywords) 

Ejemplos de uso:

 # ## our keywords are letters of the alphabet keywords = 'abcdefghijklmnopqrstuvwxyz' # ## our dictionary maps letters to their index d = my_dict([(k,i) for i,k in enumerate(keywords)]) print('Original dictionary:\n%r\n\n' % (d,)) # ## constructing a sub-dictionary with good keywords oddkeywords = keywords[::2] subd = d.subdict(oddkeywords) print('Dictionary from odd numbered keys:\n%r\n\n' % (subd,)) # ## constructing a sub-dictionary with mixture of good and bad keywords somebadkeywords = keywords[1::2] + 'A' try: subd2 = d.subdict(somebadkeywords) print("We shouldn't see this message") except KeyError: print("subd2 construction fails:") print("\toriginal dictionary doesn't contain some keys\n\n") # ## Trying again with fragile set to false try: subd3 = d.subdict(somebadkeywords, fragile=False) print('Dictionary constructed using some bad keys:\n%r\n\n' % (subd3,)) except KeyError: print("We shouldn't see this message") 

Si ejecuta todo el código anterior, debería ver (algo así como) la siguiente salida (disculpe el formato):

Diccionario original:
{‘a’: 0, ‘c’: 2, ‘b’: 1, ‘e’: 4, ‘d’: 3, ‘g’: 6, ‘f’: 5, ‘i’: 8, ‘ h ‘: 7,’ k ‘: 10,’ j ‘: 9,’ m ‘: 12,’ l ‘: 11,’ o ‘: 14,’ n ‘: 13,’ q ‘: 16,’ p ‘ : 15, ‘s’: 18, ‘r’: 17, ‘u’: 20, ‘t’: 19, ‘w’: 22, ‘v’: 21, ‘y’: 24, ‘x’: 23 , ‘z’: 25}

Diccionario de teclas de números impares:
{‘a’: 0, ‘c’: 2, ‘e’: 4, ‘g’: 6, ‘i’: 8, ‘k’: 10, ‘m’: 12, ‘o’: 14, ‘ q ‘: 16,’ s ‘: 18,’ u ‘: 20,’ w ‘: 22,’ y ‘: 24}

la construcción subd2 falla
diccionario original no contiene algunas claves

Diccionario construido usando algunas teclas malas:
{‘b’: 1, ‘d’: 3, ‘f’: 5, ‘h’: 7, ‘j’: 9, ‘l’: 11, ‘n’: 13, ‘p’: 15, ‘ r ‘: 17,’ t ‘: 19,’ v ‘: 21,’ x ‘: 23,’ z ‘: 25}

Otra más (prefiero la respuesta de Mark Longair)

 di = {'a':1,'b':2,'c':3} req = ['a','c','w'] dict([i for i in di.iteritems() if i[0] in di and i[0] in req])