je souhaiterai rechercher si une valeur est présente dans un OrderedDict. Le "soucis" c'est que ma structure se présente sous cette forme :
>>> from collections import OrderedDict as od
>>> test = od()
>>> test['test'] = {'id':'foo', 'name':'bar', 'rank': 5}
Dans l'idée, j'aimerai savoir si mon dictionnaire a bien un élément avec un id "foo". Du coup je fais comme ça :
for key, item in test.iteritems():
if item['id'] == 'foo':
print('%s ok' % item['name'])
else:
print('%s ko' % item['name'])
Jusque là, tout va bien. Maintenant le problème, c'est que potentiellement, ce dictionnaire (test) va contenir potentiellement quelques milliers d'enregistrement. A côté j'ai une autre liste, que je remplis en fonction de la présence ou non dans mon dictionnaire (ci-dessus). Du coup, je me vois difficilement faire une boucle pour check la présence de chaque élément à chaque fois (s'il est présent, il me faut les données du dictionnaire) (complexité en n², c'est pas top).
Du coup mes questions sont :
- y a-t-il une meilleur façon de procéder ? (du genre "if valeur in obj.values().values()") - est-ce que le fait de faire "if valeur in item.values()" aura les mêmes "conséquences" en terme de complexité ? Car sinon j'avais pensé "split" mon dictionnaire en deux :
un dictionnaire avec test['test'] = "foo" pour avoir la liste des items présent
un dictionnaire données['foo'] = {'id':'foo', 'name':'bar' ...}
Tu peux avoir toutes les clés sous forme de liste avec dict.keys()
Du coup tu peux tester une valeur avec un truc comme if element in dict.keys()
Si tu veux tester si un ensemble de valeurs est dans la liste des clés, ça peut se faire en transformant les deux listes en set et en utilisant les opérations sur les sets comme l'inetersection (voir la doc : http://docs.python.org/2/library/sets.html#set-objects ).
Du coup tu peux tester une valeur avec un truc comme if element in dict.keys()
dict.has_key() c'est mieux.
Mais c'est que pour les clés, pour les valeurs il n'y a pas de fonction toute faite, une boucle comme la fait Kyria est possible, mais il vaut mieux utiliser un set ou une liste pour stocker les valeurs et éviter d'avoir à parcourir tout le dictionnaire à chaque fois.
"key in dict" est beaucoup plus rapide que "key in dict.keys()" puisque le premier utilise le dict comme il se doit (accès hash), tandis que le second créé une liste temporaire de clés et fait une recherche séquentielle dedans.
Bref, pour revenir à ton problème, si tu as beaucoup de recherches à faire, il faut retourner le problème comme une chaussette : créé un dict (élément à rechercher)->(élément ou liste d'éléments correspondants). La création du dict est en O(n), la recherche aussi, c'est mieux que du O(n^2).
C'est exactement la même chose que créer un index dans une BDD.
D'ailleurs, ton problème serait peut-être plus simple en SQL (tu peux essayer postgres).
Mais il reste un point que j'ai pas saisi du coup : en pratique je cherche dans les valeurs, non les clés, donc c'est plutôt "value in items.values()" que je dois utiliser.
En fait en pratique, j'aurais besoin de faire les check sur les values des values, et jamais réellement sur les clés :/
Lord Casque Noir a écrit:
D'ailleurs, ton problème serait peut-être plus simple en SQL (tu peux essayer postgres).
Mon problème c'est que mes données viennent du SQL justement d'une structure hiérarchique à n-parents, où je dois conserver l'ordre des parents lorsque je les met sous forme de dictionnaire (d'où l'utilisation du OrderedDict), sachant qu'un parent peut apparaître plusieurs fois lors du parcours d'une arbre de parents..
Au final je vais opter pour le "double dict" (un index, l'autre de données). Ce qui sera beaucoup mieux en terme de complexité je pense.
Merci
PS: je suis en python 2.7, pas 3.x
Voir si une valeur est présent dans un dict
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Blond, bouclé, toujours le sourire aux lèvres...