web-dev-qa-db-fra.com

Dictionnaire Python: Obtenir la liste des valeurs pour la liste des clés

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]
132
FazJaxton

Une compréhension de liste semble être un bon moyen de le faire:

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

Quelques autres façons que list-comp:

  • Construire la liste et lever une exception si la clé n'est pas trouvée: map(mydict.__getitem__, mykeys)
  • Construire la liste avec 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.

77
Jon Clements

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.

34
Sklavit

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

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]
8
OdraEncoded

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]
7
Óscar López
new_dict = {x: v for x, v in mydict.items() if x in mykeys}
1
Pavel Minenkov

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}
1
abby sobh

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. 

0
Edgar Aroutiounian

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

0
mementum