Accéder à un élément arbitraire dans un dictionnaire en Python

507

Si a mydictn'est pas vide, j'accède à un élément arbitraire comme:

mydict[mydict.keys()[0]]

Y a-t-il une meilleure façon de procéder?

Stan
la source
3
Ce qu'il a dit ... ce n'est vraiment une question valable que s'il n'y a qu'un élément dans le dict, ou si vous ne vous souciez pas de savoir ce que vous récupérez.
royal
5
Oui, j'ai juste besoin d'accéder à n'importe quel élément du dict, c'est pourquoi je veux accéder au premier élément.
Stan
2
@Stan: mais comme l'a dit Greg, il n'y a pas de "premier" élément défini dans dict. alors peut-être que vous devriez changer votre question, juste pour être clair
tdihp
10
Je pense que c'est une question valable. Si vous avez besoin d'accéder à un élément arbitraire et que vous êtes sûr que le dict n'est pas vide, il peut être judicieux de demander le "premier", car le nombre d'éléments peut ne pas être connu.
kap
7
@MichaelScheper Vous devez casting à la liste: list(mydict.keys())[0].
Daniel Moskovich

Réponses:

600

Sur Python 3, de manière non destructive et itérative:

next(iter(mydict.values()))

Sur Python 2, de manière non destructive et itérative:

mydict.itervalues().next()

Si vous voulez qu'il fonctionne à la fois en Python 2 et 3, vous pouvez utiliser le sixpackage:

six.next(six.itervalues(mydict))

mais à ce stade, il est assez cryptique et je préfère votre code.

Si vous souhaitez supprimer un élément, procédez comme suit:

key, value = mydict.popitem()

Notez que "premier" peut ne pas être un terme approprié ici car il dictne s'agit pas d'un type ordonné en Python <3.6. Python 3.6+ dictsest commandé.

doublep
la source
35
Tu ne veux pas dire dict.iterkeys().next()?
John Machin
12
@John Machin: Eh bien, la question semble accéder à la valeur associée à la première clé, c'est ce que je fais également dans la réponse.
doublep
5
cela semble mieux: dict.values().__iter__().__next__():)
Vitaly Zdanevich
17
il est ennuyeux que dict.keys () ne soit pas directement itérable.
semiomant
3
pour un popitem non destructif vous pouvez faire une copie (superficielle):key, value = dict(d).popitem()
Pelle
140

Si vous n'avez besoin d'accéder qu'à un seul élément (étant le premier par hasard, car les dictés ne garantissent pas l'ordre), vous pouvez simplement le faire en Python 2 :

my_dict.keys()[0]     -> key of "first" element
my_dict.values()[0]   -> value of "first" element
my_dict.items()[0]    -> (key, value) tuple of "first" element

Veuillez noter que (au mieux de ma connaissance) Python ne garantit pas que 2 appels successifs à l'une de ces méthodes retourneront list avec le même ordre. Ceci n'est pas pris en charge avec Python3.

en Python 3 :

list(my_dict.keys())[0]     -> key of "first" element
list(my_dict.values())[0]   -> value of "first" element
list(my_dict.items())[0]    -> (key, value) tuple of "first" element
swK
la source
90
Cela ne fonctionne que dans Python 2.x, pour 3.x vous devez utiliserlist(my_dict.keys())[0]
alldayremix
6
Alors, quelle classe de complexité est-ce? Certes, list(my_dict.keys())[0]n'est-ce pas paresseux?
Evgeni Sergeev
1
Pour clarifier, ce que @alldayremix voulait dire avec ce commentaire est en python 3.x les résultats de my_dict.function () ne supportent pas l'indexation, c'est pourquoi nous devons d'abord le convertir en liste et ensuite nous pouvons utiliser l'index [0]
Noki
57

En python3, La façon:

dict.keys() 

retourne une valeur dans type: dict_keys (), nous aurons une erreur lorsque nous aurons obtenu le 1er membre des clés de dict de cette façon:

dict.keys()[0]
TypeError: 'dict_keys' object does not support indexing

Enfin, je convertis dict.keys () en liste @ 1st, et j'ai obtenu le 1er membre par la méthode d'épissage de liste:

list(dict.keys())[0]
Xb74Dkjb
la source
C'est la solution la plus simple et fonctionne à la fois en python2 et en python3.
mattmilten
Pour mon argent. Je dis que cette réponse est la plus intuitive
Thomas Valadez
Oui, mais cela ne répond pas à la question OP, qui est de savoir comment obtenir les VALEURS, pas les clés.
Mike Williamson
1
@MikeWilliamson, espérons que la plupart des lecteurs sauront comment obtenir la valeur correspondante, à partir d'une clé, à partir d'un dict python.
Eric
5
Pour obtenir un élément arbitraire, pas une clé arbitraire, vous pouvez le faire de manière analogue list(dict.values())[0].
jhin
24

obtenir une clé

next(iter(mydict))

pour obtenir une valeur

next(iter(mydict.values()))

obtenir les deux

next(iter(mydict.items())) # or next(iter(mydict.viewitems())) in python 2

Les deux premiers sont Python 2 et 3. Les deux derniers sont paresseux en Python 3, mais pas en Python 2.

maxbellec
la source
16

Comme d'autres l'ont mentionné, il n'y a pas de "premier élément", car les dictionnaires n'ont pas d'ordre garanti (ils sont implémentés sous forme de tables de hachage). Si vous voulez, par exemple, la valeur correspondant à la plus petite clé le thedict[min(thedict)]fera. Si vous vous souciez de l'ordre dans lequel les clés ont été insérées, c'est-à-dire que par "premier" vous voulez dire "inséré le plus tôt", alors dans Python 3.1 vous pouvez utiliser collections.OrderedDict , qui est également dans le prochain Python 2.7; pour les anciennes versions de Python, téléchargez, installez et utilisez le backport dict dicté (2.4 et versions ultérieures) que vous pouvez trouver ici .

Python 3.7 Les dits sont désormais ordonnés par insertion.

Alex Martelli
la source
11

Que dis-tu de ça. Pas encore mentionné ici.

py 2 & 3

a = {"a":2,"b":3}
a[list(a)[0]] # the first element is here
>>> 2
animaacija
la source
5
dict.values()renvoie une vue, donc devrait être O (1). list(a)renvoie une nouvelle liste, serait donc O (n).
boycy
Il semble également que cela ne fonctionne pas en python2 si a = {"a": {"1"}}
qasimzee
11

Ignorant les problèmes liés à l'ordre des dicts, cela pourrait être mieux:

next(dict.itervalues())

De cette façon, nous évitons la recherche d'éléments et générons une liste de clés que nous n'utilisons pas.

Python3

next(iter(dict.values()))
Matt Joiner
la source
2
values ​​() fera une copie de toutes les valeurs (tout comme les touches () pour les clés), cela fera donc de nombreuses opérations O (n ^ 2).
Glenn Maynard
Alors, la version OPs? Je vais changer cela pour utiliser un itérateur alors.
Matt Joiner
4
Ce n'est que Python 2. Pour Python 3, nous devons next(iter(dict.values()))obtenir le même résultat sans créer la liste.
kap
6

En python3

list(dict.values())[0]
Oleg Matei
la source
4
Que se passe-t-il si le dictionnaire contient un milliard d'entrées? :)
Fábio Dias
2

Vous pouvez toujours faire:

for k in sorted(d.keys()):
    print d[k]

Cela vous donnera un ensemble de clés triées de manière cohérente (par rapport au .hash () intégré, je suppose) sur lesquelles vous pouvez traiter si le tri a une signification pour vous. Cela signifie par exemple que les types numériques sont triés de manière cohérente même si vous développez le dictionnaire.

EXEMPLE

# lets create a simple dictionary
d = {1:1, 2:2, 3:3, 4:4, 10:10, 100:100}
print d.keys()
print sorted(d.keys())

# add some other stuff
d['peter'] = 'peter'
d['parker'] = 'parker'
print d.keys()
print sorted(d.keys())

# some more stuff, numeric of different type, this will "mess up" the keys set order
d[0.001] = 0.001
d[3.14] = 'pie'
d[2.71] = 'apple pie'
print d.keys()
print sorted(d.keys())

Notez que le dictionnaire est trié lors de l'impression. Mais le jeu de clés est essentiellement une table de hachage!

Philipp Meier
la source
2

Pour Python 2 et 3:

import six

six.next(six.itervalues(d))
oblalex
la source
Cela ne fournit pas de réponse à la question. Pour critiquer ou demander des éclaircissements à un auteur, laissez un commentaire sous son article.
Martin Tournoij
Cela répond exactement à la question Is there any better way to do this?de manière brève.
oblalex
Cette réponse a déjà été donnée deux fois, dont une sur ce site depuis près de 5 ans. Il s'agit d'un commentaire sur une autre réponse (comme dans: voici comment améliorer la réponse pour la faire fonctionner avec Python 2 et 3 ), et non une "nouvelle" réponse en tant que telle. Le système de révision de SO a automatiquement placé une note quelque peu inutile dans ce cas ...
Martin Tournoij
Non monsieur. Vous avez ajouté cette variante à votre réponse de 5 ans il y a seulement 17 heures, 1 heure après avoir écrit cette réponse. Essayez d'utiliser «trouver» sur cette page pour «six» mot et vous ne trouverez que 6 correspondances que dans ces 2 réponses. Quoi qu'il en soit, cette réponse vous dérange-t-elle vraiment? Je pense que cela pourrait aider d'autres personnes à l'avenir et c'est OK. Alors, quel est le problème?
oblalex
C'est parce qu'à mon humble avis, cette réponse aurait dû être une modification de ce message en premier lieu. Sans la modification, les gens devraient faire défiler un certain nombre de pages vers le bas pour voir votre réponse; Pensez-vous que ce soit plus utile que de modifier une réponse très positive qui est presque exactement la même que la vôtre?
Martin Tournoij
0
first_key, *rest_keys = mydict
user1994083
la source
11
Merci pour cet extrait de code, qui pourrait fournir une aide immédiate limitée. Une explication appropriée améliorerait considérablement sa valeur à long terme en montrant pourquoi c'est une bonne solution au problème, et la rendrait plus utile aux futurs lecteurs avec d'autres questions similaires. Veuillez modifier votre réponse pour ajouter des explications, y compris les hypothèses que vous avez faites.
Suraj Rao
-1

Pas de bibliothèques externes, fonctionne à la fois sur Python 2.7 et 3.x:

>>> list(set({"a":1, "b": 2}.values()))[0]
1

Pour la clé aribtrary, il suffit de laisser de côté .values ​​()

>>> list(set({"a":1, "b": 2}))[0]
'a'
Thomas Browne
la source
-2

Le sous dict- classement est une méthode, mais pas efficace. Ici, si vous fournissez un entier, il reviendra d[list(d)[n]], sinon accédez au dictionnaire comme prévu:

class mydict(dict):
    def __getitem__(self, value):
        if isinstance(value, int):
            return self.get(list(self)[value])
        else:
            return self.get(value)

d = mydict({'a': 'hello', 'b': 'this', 'c': 'is', 'd': 'a',
            'e': 'test', 'f': 'dictionary', 'g': 'testing'})

d[0]    # 'hello'
d[1]    # 'this'
d['c']  # 'is'
jpp
la source