resueltos - lista dentro de un diccionario python
Diccionario de Python: Obtener una lista de valores para la lista de claves (10)
¿Existe una forma incorporada / rápida de usar una lista de claves para un diccionario para obtener una lista de los elementos correspondientes?
Por ejemplo, tengo:
>>> mydict = {''one'': 1, ''two'': 2, ''three'': 3}
>>> mykeys = [''three'', ''one'']
¿Cómo puedo usar mykeys
para obtener los valores correspondientes en el diccionario como una lista?
>>> mydict.WHAT_GOES_HERE(mykeys)
[3, 1]
Aquí hay tres formas.
Levantando KeyError
cuando no se encuentra la clave:
result = [mapping[k] for k in iterable]
Valores predeterminados para claves faltantes.
result = [mapping.get(k, default_value) for k in iterable]
Omitiendo las teclas faltantes.
found_keys = mapping.keys() & iterable
result = [mapping[k] for k in iterable if k in found_keys]
O simplemente mydict.keys()
Esa es una llamada de método integrada para diccionarios. También explore mydict.values()
y mydict.items()
.
// Ah, OP post me confundió.
Pandas lo hace de forma muy elegante, aunque las comprensiones de la lista siempre serán más técnicamente pitónicas. No tengo tiempo para hacer una comparación de velocidad en este momento (volveré más tarde y lo pondré):
import pandas as pd
mydict = {''one'': 1, ''two'': 2, ''three'': 3}
mykeys = [''three'', ''one'']
temp_df = pd.DataFrame().append(mydict)
# You can export DataFrames to a number of formats, using a list here.
temp_df[mykeys].values[0]
# Returns: array([ 3., 1.])
# If you want a dict then use this instead:
# temp_df[mykeys].to_dict(orient=''records'')[0]
# Returns: {''one'': 1.0, ''three'': 3.0}
Prueba esto:
mydict = {''one'': 1, ''two'': 2, ''three'': 3}
mykeys = [''three'', ''one'',''ten'']
newList=[mydict[k] for k in mykeys if k in mydict]
print newList
[3, 1]
Prueba esto:
mydict = {''one'': 1, ''two'': 2, ''three'': 3}
mykeys = [''three'', ''one''] # if there are many keys, use a set
[mydict[k] for k in mykeys]
=> [3, 1]
Tras el cierre de Python: forma eficiente de crear una lista a partir de valores dict con un orden determinado
Recuperando las claves sin construir la lista:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import collections
class DictListProxy(collections.Sequence):
def __init__(self, klist, kdict, *args, **kwargs):
super(DictListProxy, self).__init__(*args, **kwargs)
self.klist = klist
self.kdict = kdict
def __len__(self):
return len(self.klist)
def __getitem__(self, key):
return self.kdict[self.klist[key]]
myDict = {''age'': ''value1'', ''size'': ''value2'', ''weigth'': ''value3''}
order_list = [''age'', ''weigth'', ''size'']
dlp = DictListProxy(order_list, myDict)
print('',''.join(dlp))
print()
print(dlp[1])
La salida:
value1,value3,value2
value3
Que coincide con el orden dado por la lista
Un par de otras formas además de la compilación de listas:
- Crear lista y lanzar excepción si no se encuentra la clave:
map(mydict.__getitem__, mykeys)
- Lista de compilación con
None
si no se encuentra la clave:map(mydict.get, mykeys)
Alternativamente, al usar operator.itemgetter
puede devolver una tupla:
from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required
Una lista de comprensión parece ser una buena manera de hacer esto:
>>> [mydict[x] for x in mykeys]
[3, 1]
Una pequeña comparación de velocidad:
Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec 7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[1]: l = [0,1,2,3,2,3,1,2,0]
In[2]: m = {0:10, 1:11, 2:12, 3:13}
In[3]: %timeit [m[_] for _ in l] # list comprehension
1000000 loops, best of 3: 762 ns per loop
In[4]: %timeit map(lambda _: m[_], l) # using ''map''
1000000 loops, best of 3: 1.66 µs per loop
In[5]: %timeit list(m[_] for _ in l) # a generator expression passed to a list constructor.
1000000 loops, best of 3: 1.65 µs per loop
In[6]: %timeit map(m.__getitem__, l)
The slowest run took 4.01 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 853 ns per loop
In[7]: %timeit map(m.get, l)
1000000 loops, best of 3: 908 ns per loop
In[33]: from operator import itemgetter
In[34]: %timeit list(itemgetter(*l)(m))
The slowest run took 9.26 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 739 ns per loop
Entonces, la comprensión de la lista y el cambio de elementos son las formas más rápidas de hacerlo.
ACTUALIZACIÓN: Para grandes listas aleatorias y mapas tuve resultados un poco diferentes:
Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec 7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)
%timeit f(m)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l] # list comprehension
%timeit map(m.__getitem__, l)
%timeit list(m[_] for _ in l) # a generator expression passed to a list constructor.
%timeit map(m.get, l)
%timeit map(lambda _: m[_], l)
1000 loops, best of 3: 1.14 ms per loop
1000 loops, best of 3: 1.68 ms per loop
100 loops, best of 3: 2 ms per loop
100 loops, best of 3: 2.05 ms per loop
100 loops, best of 3: 2.19 ms per loop
100 loops, best of 3: 2.53 ms per loop
100 loops, best of 3: 2.9 ms per loop
Entonces, en este caso, el ganador claro es f = operator.itemgetter(*l); f(m)
f = operator.itemgetter(*l); f(m)
, y claro outsider: map(lambda _: m[_], l)
.
reduce(lambda x,y: mydict.get(y) and x.append(mydict[y]) or x, mykeys,[])
en caso de que haya llaves no en dict.