web-dev-qa-db-fra.com

Python - Retourne la première clé N: paires de valeurs de dict

Considérons le dictionnaire suivant, d:

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

Je veux renvoyer les N premières paires clé: valeur de d (N <= 4 dans ce cas). Quelle est la méthode la plus efficace pour le faire?

56
Jason Strimpel

Il n’existe pas de clé "n", car une dict ne se souvient pas des clés insérées en premier.

Vous pouvez cependant obtenir tout _ n paires clé-valeur

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

Ceci utilise la mise en oeuvre de take à partir des recettes itertools :

from itertools import islice

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

Regardez le travail en ligne: ideone

70
Mark Byers

Un moyen très efficace de tout récupérer consiste à combiner la compréhension de liste ou de dictionnaire avec le découpage en tranches. Si vous n'avez pas besoin de commander les éléments (vous voulez juste n paires aléatoires), vous pouvez utiliser une compréhension du 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 créer une liste des clés du dictionnaire et en découpant cette liste, vous évitez de "toucher" à des clés inutiles lorsque vous créez le nouveau dictionnaire. 

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

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 compliqué:

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

ou si vous avez aussi besoin des clés:

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
48
monotasker

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

Le collections.OrderedDict class est disponible si c'est ce dont vous avez besoin. Vous pouvez efficacement obtenir ses quatre premiers éléments

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 paresseux une tranche d’éléments à partir de n’importe quel itérateur. Si vous voulez que le résultat soit réutilisable, vous devez le convertir en liste ou quelque chose du genre, comme ceci:

x = list(itertools.islice(d.items(), 0, 4))
9
Jeremy Banks
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, tournez la vue (dict_items) en itérateur, puis répétez-la avec next ().

5
cop4587

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]}
3
user2623954

Voir PEP 0265 sur le tri des dictionnaires. Ensuite, utilisez le code itérable précité.

Si vous avez besoin de plus d'efficacité dans les paires clé-valeur triées. Utilisez une structure de données différente. C’est-à-dire un système qui conserve l’ordre trié et les associations clé-valeur.

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

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 nécessaire, c'est une opération lazy qui évite la création d'une liste explicite de clés ou d'éléments. 

Si vous devez d’abord trier les clés, il n’est pas possible d’utiliser une fonction comme keys = foo.keys(); keys.sort() ou sorted(foo.iterkeys()), vous devrez créer une liste explicite de clés. Puis coupez ou parcourez la première N keys.

BTW pourquoi vous souciez-vous de la manière «efficace»? Avez-vous profilé votre programme? Si ce n'est pas le cas, utilisez d'abord le chemin évident et facile à comprendre . Il y a de fortes chances que cela se passe plutôt bien sans goulot d'étranglement.

1
9000

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

envisager 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 :) espérons que cela aide!

0
Vivek Ananthan

ajoutez simplement une réponse en utilisant Zip,

{k: d[k] for k, _ in Zip(d, range(n))}
0
Peter Li

Vous pouvez aborder ce problème de plusieurs manières. Si l'ordre est important, vous pouvez le faire:

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

Si l'ordre ne vous concerne pas, vous pouvez le faire:

for i in range(4):
  item = d.popitem()
0
g.d.d.c

Le dictionnaire ne conserve aucun ordre. Par conséquent, avant de choisir les N premières paires de valeurs-clés, nous allons le 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 'N' éléments les plus importants, 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 meilleurs é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
Jyothish Arumugam

Cela peut ne pas être très élégant, mais fonctionne 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