Partage
  • Partager sur Facebook
  • Partager sur Twitter

Voir si une valeur est présent dans un dict

(<valeur> in "dict.values().values()") Meilleure façon de procéder

    22 juillet 2013 à 17:44:01

    Bonjour,

    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' ...}

     Est-ce mieux ? Ou ça ne change rien ?

    Je vous remercie pour vos remarques et votre aide

    • Partager sur Facebook
    • Partager sur Twitter
      22 juillet 2013 à 22:29:00

      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 ).

      • Partager sur Facebook
      • Partager sur Twitter

      Blond, bouclé, toujours le sourire aux lèvres...

        22 juillet 2013 à 23:34:54

        LoupSolitaire a écrit:

        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.

        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          23 juillet 2013 à 0:32:41

          "dict.has_key() c'est mieux."

          La documentation dit -> Test for the presence of key in the dictionary. <tt class="xref py py-meth docutils literal">has_key()</tt> is deprecated in favor of <tt class="docutils literal">key in d</tt>.

          Mais en plus il est en version 3, si on remarque ses print(...), du coup cette fonction n'existe plus.

          • Partager sur Facebook
          • Partager sur Twitter
            23 juillet 2013 à 8:26:47

            "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).

            • Partager sur Facebook
            • Partager sur Twitter
              23 juillet 2013 à 9:21:56

              Merci à vous. 

              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

              • Partager sur Facebook
              • Partager sur Twitter

              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.
              • Editeur
              • Markdown