Existe-t-il un moyen intégré/rapide d'utiliser une liste de clés d'un dictionnaire pour obtenir une liste des éléments correspondants?
Par exemple j'ai:
>>> mydict = {'one': 1, 'two': 2, 'three': 3}
>>> mykeys = ['three', 'one']
Comment utiliser mykeys
pour obtenir les valeurs correspondantes dans le dictionnaire sous forme de liste?
>>> mydict.WHAT_GOES_HERE(mykeys)
[3, 1]
Une compréhension de liste semble être un bon moyen de le faire:
>>> [mydict[x] for x in mykeys]
[3, 1]
Quelques autres façons que list-comp:
map(mydict.__getitem__, mykeys)
None
si clé non trouvée: map(mydict.get, mykeys)
Sinon, l'utilisation de operator.itemgetter
peut renvoyer un tuple:
from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required
Remarque : dans Python3, map
renvoie un itérateur plutôt qu'une liste. Utilisez list(map(...))
pour une liste.
Une petite comparaison de vitesse:
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
La compréhension de liste et itemgetter sont donc les moyens les plus rapides de le faire.
UPDATE: Pour les grandes listes aléatoires et les cartes, mes résultats sont légèrement différents:
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
Donc, dans ce cas, le gagnant clair est f = operator.itemgetter(*l); f(m)
, et l’extérieur clair: map(lambda _: m[_], l)
.
UPDATE pour Python 3.6.4:
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 list(map(m.__getitem__, l))
%timeit list(m[_] for _ in l) # a generator expression passed to a list constructor.
%timeit list(map(m.get, l))
%timeit list(map(lambda _: m[_], l)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Donc, les résultats pour Python 3.6.4 sont presque les mêmes.
Essaye ça:
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]
Voici trois façons.
Relancer KeyError
lorsque la clé n'est pas trouvée:
result = [mapping[k] for k in iterable]
Valeurs par défaut pour les clés manquantes.
result = [mapping.get(k, default_value) for k in iterable]
Ignorer les clés manquantes.
result = [mapping[k] for k in iterable if k in mapping]
Essaye ça:
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]
new_dict = {x: v for x, v in mydict.items() if x in mykeys}
Les Pandas le font avec beaucoup d’élégance, bien que la compréhension des listes reste toujours techniquement en Pythonique. Je n'ai pas le temps de faire une comparaison de vitesse maintenant (je reviendrai plus tard et le mettrai dedans):
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}
Ou simplement mydict.keys()
C'est un appel à une méthode intégrée pour les dictionnaires. Explorez également mydict.values()
et mydict.items()
.
// Ah, OP post m'a confondu.
Après la fermeture de Python: moyen efficace de créer une liste à partir de valeurs dict avec un ordre donné
Récupérer les clés sans construire la liste:
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])
Le résultat:
value1,value3,value2
value3
Qui correspond à l'ordre donné par la liste