Considérez le dictionnaire suivant, d:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

Je veux retourner la première N clé: paires de valeurs de d (N <= 4 dans ce cas). Quelle est la méthode la plus efficace pour ce faire?

98
Jason Strimpel 1 nov. 2011 à 23:15

16 réponses

Meilleure réponse

Il n'y a rien de tel dans les "premières n" clés car un dict ne se souvient pas quelles clés ont été insérées en premier.

Vous pouvez obtenir toutes n paires de valeurs-clés:

n_items = take(n, d.iteritems())

Cela utilise l'implémentation de take à partir des itertools recettes :

from itertools import islice

def take(n, iterable):
    "Return first n items of the iterable as a list"
    return list(islice(iterable, n))

Voyez-le fonctionner en ligne: ideone


Mise à jour pour Python 3.6

n_items = take(n, d.items())
103
ofir_aghai 21 août 2019 à 12:43

Le dictionnaire ne maintient aucun ordre, donc avant de sélectionner les N premières paires de valeurs de clés, nous pouvons les trier.

import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values

Maintenant, nous pouvons récupérer les éléments N supérieurs: en utilisant la structure de la méthode comme ceci:

def return_top(elements,dictionary_element):
    '''Takes the dictionary and the 'N' elements needed in return
    '''
    topers={}
    for h,i in enumerate(dictionary_element):
        if h<elements:
            topers.update({i:dictionary_element[i]})
    return topers

Pour obtenir les 2 premiers éléments, utilisez simplement cette structure:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)
0
Sketchy Coder 12 sept. 2017 à 12:09

Considérer un dict

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

from itertools import islice
n = 3
list(islice(d.items(),n))

Islice fera l'affaire :) j'espère que ça aide!

0
Vivek Ananthan 8 févr. 2019 à 12:18

Les dict de Python ne sont pas ordonnés, il est donc inutile de demander les "premières N" clés.

La classe collections.OrderedDict est disponible si c'est ce que vous avoir besoin. Vous pouvez obtenir efficacement ses quatre premiers éléments comme

import itertools
import collections

d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)

for key, value in x:
    print key, value

itertools.islice vous permet de prendre paresseusement une tranche d'éléments de tout itérateur. Si vous voulez que le résultat soit réutilisable, vous devez le convertir en liste ou quelque chose comme ça:

x = list(itertools.islice(d.items(), 0, 4))
11
Jeremy Banks 1 nov. 2011 à 19:18

Vous pouvez aborder cela de plusieurs façons. Si la commande est importante, vous pouvez le faire:

for key in sorted(d.keys()):
  item = d.pop(key)

Si la commande n'est pas un problème, vous pouvez le faire:

for i in range(4):
  item = d.popitem()
0
g.d.d.c 1 nov. 2011 à 19:18

Voir PEP 0265 sur le tri des dictionnaires. Utilisez ensuite le code itérable susmentionné.

Si vous avez besoin de plus d'efficacité dans les paires clé-valeur triées. Utilisez une structure de données différente. Autrement dit, celui qui maintient l'ordre trié et les associations valeur-clé.

Par exemple.

import bisect

kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))

print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
3
silverjam 31 janv. 2014 à 21:10

J'ai essayé quelques-unes des réponses ci-dessus et je note que certaines d'entre elles dépendent de la version et ne fonctionnent pas dans la version 3.7.

Je note également que depuis la version 3.6, tous les dictionnaires sont classés par ordre dans lequel les éléments sont insérés.

Bien que les dictionnaires soient commandés depuis la version 3.6, certaines des déclarations auxquelles vous vous attendez à travailler avec des structures ordonnées ne semblent pas fonctionner.

La réponse à la question OP qui a fonctionné le mieux pour moi.

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
0
Mark Kortink 17 nov. 2019 à 02:20

Pour Python 3 et supérieur, Pour sélectionner les n premières paires

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}
0
Shivpe_R 3 nov. 2017 à 05:14

Je ne l'ai pas vu ici. Ne sera pas commandé mais le plus simple syntaxiquement si vous avez juste besoin de prendre quelques éléments d'un dictionnaire.

n = 2
{key:value for key,value in d.items()[0:n]}
6
user2623954 27 janv. 2016 à 02:53

Un moyen très efficace de récupérer n'importe quoi est de combiner des compréhensions de liste ou de dictionnaire avec le découpage. Si vous n'avez pas besoin de commander les articles (vous voulez juste n paires aléatoires), vous pouvez utiliser une compréhension de dictionnaire comme celle-ci:

# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}

Généralement, une compréhension comme celle-ci est toujours plus rapide à exécuter que la boucle équivalente "pour x dans y". De plus, en utilisant .keys () pour faire une liste des clés de dictionnaire et en découpant cette liste, vous évitez de «toucher» les touches inutiles lorsque vous créez le nouveau dictionnaire.

Si vous n'avez pas besoin des clés (uniquement les valeurs), vous pouvez utiliser une compréhension de liste:

first2vals = [v for v in mydict.values()[:2]]

Si vous avez besoin que les valeurs soient triées en fonction de leurs clés, ce n'est pas beaucoup plus difficile:

first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]

Ou si vous avez également besoin des clés:

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
76
Hendy Irawan 17 nov. 2017 à 10:03
foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
    print(next(iterator))

Fondamentalement, transformez la vue (dict_items) en itérateur, puis répétez-la avec next ().

8
cop4587 20 sept. 2017 à 12:05

En py3, cela fera l'affaire

{A:N for (A,N) in [x for x in d.items()][:4]}

{'a': 3, 'b': 2, 'c': 3, 'd': 4}

1
farid khafizov 2 déc. 2019 à 21:21

Pour obtenir les N premiers éléments de votre dictionnaire python, vous pouvez utiliser la ligne de code suivante:

list(dictionaryName.items())[:N]

Dans votre cas, vous pouvez le changer en:

list(d.items())[:4]
3
MartenCatcher 6 nov. 2019 à 09:57

Ajoutez simplement une réponse en utilisant zip,

{k: d[k] for k, _ in zip(d, range(n))}
1
Peter Li 12 avril 2019 à 21:15

Ce n'est peut-être pas très élégant, mais ça marche pour moi:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

x= 0
for key, val in d.items():
    if x == 2:
        break
    else:
        x += 1
        # Do something with the first two key-value pairs
0
Thorsten Stehlik 12 août 2019 à 12:08

Cela dépend de ce qui est «le plus efficace» dans votre cas.

Si vous voulez juste un échantillon semi-aléatoire d'un énorme dictionnaire foo, utilisez foo.iteritems() et prenez-en autant de valeurs que vous en avez besoin, c'est une opération paresseuse qui évite la création d'une liste explicite de clés ou articles.

Si vous devez d'abord trier les clés, il n'y a aucun moyen d'utiliser quelque chose comme keys = foo.keys(); keys.sort() ou sorted(foo.iterkeys()), vous devrez créer une liste explicite de clés. Ensuite, coupez ou parcourez le premier N keys.

BTW pourquoi vous souciez-vous de la manière «efficace»? Avez-vous profilé votre programme? Si vous ne l'avez pas fait, utilisez d'abord la méthode évidente et facile à comprendre . Il y a de fortes chances qu'il se porte plutôt bien sans devenir un goulot d'étranglement.

1
9000 1 nov. 2011 à 19:37
7971618