Jayesh
Tengo un gran objeto de diccionario 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) de dividir dicho diccionario en subconjuntos?
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 forma más elegante que esta.
marca longair
Tu podrías intentar:
dict((k, bigdict[k]) for k in ('l', 'm', 'n'))
… o en Pitón 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 sabe que las claves estarán en el diccionario; vea su respuesta si no puede hacer esa suposición. Alternativamente, como timbo señala en los comentarios, si desea una clave que falta en bigdict
mapear a None
tu puedes hacer:
{k: bigdict.get(k, None) for k in ('l', 'm', 'n')}
Si está utilizando Python 3 y solamente quiere claves en el dictado nuevo que realmente existen en el original, puede usar el hecho para ver objetos implementar algunas operaciones establecidas:
{k: bigdict[k] for k in bigdict.keys() & {'l', 'm', 'n'}}
-
fallará si
bigdict
no contienek
– Håvard S
18 de marzo de 2011 a las 13:29
-
{k: bigdict.get(k,None) for k in ('l', 'm', 'n')}
se ocupará de la situación en la que falta una clave específica en el diccionario de origen configurando la clave en el nuevo dict en Ninguno– timbó
21 de diciembre de 2013 a las 22:44
-
@MarkLongair Dependiendo del caso de uso {k: bigdict[k] for k in (‘l’,’m’,’n’) if k in bigdict} podría ser mejor, ya que solo almacena las claves que realmente tienen valores.
– Brian Wylie
07/03/2014 a las 22:20
-
bigdict.keys() & {'l', 'm', 'n'}
==>bigdict.viewkeys() & {'l', 'm', 'n'}
para Python2.7– kxr
25 de agosto de 2016 a las 15:58
-
¿Qué pasa si mi
dict
¿es demasiado grande?– Adamantish
17 de marzo de 2021 a las 22:12
Havard S
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)
-
+1 para el comportamiento alternativo de excluir una clave si no está en bigdict en lugar de establecerla en Ninguno.
– dhj
12/06/2014 a las 18:35
-
Alternativamente:
dict((k,bigdict.get(k,defaultVal) for k in wanted_keys)
si debe tener todas las llaves.– Thomas Andrews
1 mayo 2018 a las 20:57
-
Esta respuesta se salva con una “t”.
– sakura shinken
29 de mayo de 2019 a las 7:42
-
También una variante un poco más corta (sintaxis) de su solución es cuando se usa
{}
es decir{k: bigdict[k] for k in wanted_keys if k in bigdict}
– Arty
4 de octubre de 2021 a las 3:42
Sklavit
Un poco de comparación de velocidad para todos los métodos mencionados:
ACTUALIZADO el 2020.07.13 (gracias a @user3780389): SOLO para claves de bigdict.
IPython 5.5.0 -- An enhanced Interactive Python.
Python 2.7.18 (default, Aug 8 2019, 00:00:00)
[GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux2
import numpy.random as nprnd
...: keys = nprnd.randint(100000, size=10000)
...: bigdict = dict([(_, nprnd.rand()) for _ in range(100000)])
...:
...: %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 {key:bigdict[key] for key in set(keys) & set(bigdict.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: 2.36 ms per loop
100 loops, best of 3: 2.87 ms per loop
100 loops, best of 3: 3.65 ms per loop
100 loops, best of 3: 7.14 ms per loop
1 loop, best of 3: 577 ms per loop
1 loop, best of 3: 563 ms per loop
Como era de esperar: las comprensiones de diccionario son la mejor opción.
-
Las primeras 3 operaciones están haciendo algo diferente a las dos últimas y darán como resultado un error si
key
no existe enbigdict
.– nada101
19 de junio de 2020 a las 1:56
-
bonito. tal vez valga la pena agregar
{key:bigdict[key] for key in bigdict.keys() & keys}
de la solución aceptada que logra el filtro mientras que en realidad es más rápido (en mi máquina) que el primer método que enumera que no filtra. En realidad,{key:bigdict[key] for key in set(keys) & set(bigdict.keys())}
parece ser aún más rápido para estos juegos de llaves tan grandes…– teichert
8 julio 2020 a las 18:30
-
@telchert te estás perdiendo, que en la comparación de velocidad de entrega bigdict.keys() & keys no son conjuntos. Y con la conversión explícita a conjuntos, la solución aceptada no es tan rápida.
– Sklavit
18 oct 2021 a las 13:58
la cabeza de escoba
interesting_keys = ('l', 'm', 'n')
subdict = {x: bigdict[x] for x in interesting_keys if x in bigdict}
Esta respuesta usa una comprensión de diccionario similar a la respuesta seleccionada, pero no 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')}
-
… pero si el dictado grande es ENORME, aún se repetirá por completo (esta es una operación O (n)), mientras que el inverso solo tomaría 3 elementos (cada uno una operación O (1)).
– exterior reforzado
5 oct 2015 a las 16:08
-
La pregunta es sobre un diccionario de solo 16 claves.
– Maullar
06/10/2015 a las 17:09
phimuemue
Quizás:
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 pitón 3
subdict={a:bigdict[a] for a in ['l','m','n'] if a in bigdict}
-
… pero si el dictado grande es ENORME, aún se repetirá por completo (esta es una operación O (n)), mientras que el inverso solo tomaría 3 elementos (cada uno una operación O (1)).
– exterior reforzado
5 oct 2015 a las 16:08
-
La pregunta es sobre un diccionario de solo 16 claves.
– Maullar
06/10/2015 a las 17:09
kevin grimm
Un enfoque alternativo si desea conservar la mayoría de las claves mientras elimina algunas:
{k: bigdict[k] for k in bigdict.keys() if k not in ['l', 'm', 'n']}
-
Aún más corto:
{k: v for k, v in bigdict.items() if k not in ['l', 'm', 'n']}
– Pierresegonne
11 oct 2021 a las 13:42