252 votes

Dictionnaire : Obtenir une liste de valeurs pour une liste de clés

Existe-t-il un moyen intégré/rapide d'utiliser une liste de clés dans un dictionnaire pour obtenir une liste d'éléments correspondants ?

Par exemple, j'ai :

>>> mydict = {'one': 1, 'two': 2, 'three': 3}
>>> mykeys = ['three', 'one']

Comment puis-je utiliser mykeys pour obtenir les valeurs correspondantes dans le dictionnaire sous forme de liste ?

>>> mydict.WHAT_GOES_HERE(mykeys)
[3, 1]

284voto

FazJaxton Points 2850

La compréhension d'une liste semble être un bon moyen de le faire :

>>> [mydict[x] for x in mykeys]
[3, 1]

127voto

Jon Clements Points 51556

Il y a d'autres moyens que la liste de contrôle :

  • Construit la liste et lève une exception si la clé n'est pas trouvée : map(mydict.__getitem__, mykeys)
  • Construire une liste avec None si la clé n'est pas trouvée : map(mydict.get, mykeys)

On peut aussi utiliser operator.itemgetter peut retourner un tuple :

from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required

Note : en Python3, map renvoie un itérateur plutôt qu'une liste. Utilisez list(map(...)) pour une liste.

70voto

Sklavit Points 21

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 la liste et l'itemgetter sont donc les moyens les plus rapides d'y parvenir.

Mise à jour

Pour les grandes listes aléatoires et les cartes, j'ai obtenu des résultats un peu 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)
1000 loops, best of 3: 1.14 ms per loop

%timeit list(itemgetter(*l)(m))
1000 loops, best of 3: 1.68 ms per loop

%timeit [m[_] for _ in l]  # list comprehension
100 loops, best of 3: 2 ms per loop

%timeit map(m.__getitem__, l)
100 loops, best of 3: 2.05 ms per loop

%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
100 loops, best of 3: 2.19 ms per loop

%timeit map(m.get, l)
100 loops, best of 3: 2.53 ms per loop

%timeit map(lambda _: m[_], l)
100 loops, best of 3: 2.9 ms per loop

Donc, dans ce cas, le grand gagnant est f = operator.itemgetter(*l); f(m) et un outsider clair : map(lambda _: m[_], l) .

Mise à jour 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)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit list(itemgetter(*l)(m))
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit [m[_] for _ in l]  # list comprehension
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(map(m.__getitem__, l))
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(map(m.get, l))
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(map(lambda _: m[_], l)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Ainsi, les résultats pour Python 3.6.4 sont presque les mêmes.

18voto

OdraEncoded Points 1091

Voici trois façons de le faire.

Raising 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]

Sauter les clés manquantes.

result = [mapping[k] for k in iterable if k in mapping]

10voto

Essayez ç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]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X