{"id":964,"date":"2013-04-25T22:21:05","date_gmt":"2013-04-25T20:21:05","guid":{"rendered":"http:\/\/saladtomatonion.com\/blog\/?p=964"},"modified":"2013-04-26T09:00:42","modified_gmt":"2013-04-26T07:00:42","slug":"grouper-des-objets-selon-un-certain-critere-en-python","status":"publish","type":"post","link":"https:\/\/saladtomatonion.com\/blog\/2013\/04\/25\/grouper-des-objets-selon-un-certain-critere-en-python\/","title":{"rendered":"Grouper des objets selon un certain crit\u00e8re en python"},"content":{"rendered":"<p>Ajourd&rsquo;hui, on fait des cat\u00e9gories. J&rsquo;ai eu besoin d&rsquo;\u00e9tablir des listes d&rsquo;objets selon un certain crit\u00e8re, et retrouver mes listes par la valeur du crit\u00e8re. Par exemple, dans une liste d&rsquo;objet, grouper les fruits, les animaux, et les machines-outils.<!--more--><\/p>\n<p>Imaginons que j&rsquo;ai une liste d&rsquo;objets qui portent tous le champ <code>type<\/code>.<\/p>\n<p>Je pourrais proc\u00e9der via une m\u00e9thode \u00e9vidente comme suit.<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">\r\nobjects = something_to_get_objects()\r\nresult = dict()\r\nfor o in objects:\r\n    if o.type not in result:\r\n        result[o.type] = list()\r\n    result[o.type].append(o)<\/pre>\n<blockquote><p>Au lieu d&rsquo;utiliser un champ de l&rsquo;objet, je pourrais tout autant utiliser une fonction qui me retournerait une cl\u00e9 pour cet objet.<\/p><\/blockquote>\n<p>\u00c7a fonctionne, mais je trouve que \u00e7a pourrait \u00eatre plus \u00e9l\u00e9gant. Je pourrais par exemple d\u00e9j\u00e0 utiliser un <code>defaultdict<\/code> pour que chaque nouvelle cl\u00e9 \u00e0 laquelle j\u2019acc\u00e9derai soit d\u00e9j\u00e0 peupl\u00e9e par une liste vide.<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">from collections import defaultdict\r\nobjects = something_to_get_objects()\r\nresult = defaultdict(list)\r\nfor o in objects:\r\n    result[o.type].append(o)<\/pre>\n<p>C&rsquo;est d\u00e9j\u00e0 plus propre, mais j&rsquo;ai l&rsquo;impression que la lib <code>itertools<\/code> me donnerait bien des optimisations pour un tr\u00e8s grand nombre d&rsquo;objets.<\/p>\n<p>Et voil\u00e0 comment faire.<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">objects = something_to_get_objects()\r\n# Sort is necessary for the next step\r\nsorted_objects = sorted(objects, key=lambda x: x.type)\r\n\r\n# groupby tool return a groupby object, which iterator over grouper objects\r\ngroupby = itertools.groupby(sorted_objects, key=lambda x: x.type)\r\n\r\n# grouper objects are 2-tuples with a key and an iterator\r\n# x[0] is the key\r\n# x[1] is the iterator and I evaluate it to a list\r\nresult = dict((x[0], list(x[1]) for x in groupby)\r\n\r\n# It's a dict!\r\nfor o in result['power-tool']: print o<\/pre>\n<p>J&rsquo;aurais pu tout \u00e9crire sur une seule ligne mais \u00e7a aurait \u00e9t\u00e9 overkill, non? Pour une fois, h\u00e9las, le code qui utilise itertools me para\u00eet moins compact et \u00e9l\u00e9gant que la boucle avec le <code>defaultdict<\/code>. Est-il par contre plus performant, surtout pour de grosses listes en entr\u00e9e?<\/p>\n<p>Je suis par ailleurs oblig\u00e9 d&rsquo;\u00e9valuer l&rsquo;it\u00e9rateur du <code>grouper<\/code> au moment o\u00f9 je construis le dictionnaire, ce que je trouve dommage. Mais \u00e7a s&rsquo;explique par le fait qu&rsquo;une fois l&rsquo;it\u00e9ration sur les cl\u00e9s faite, l&rsquo;it\u00e9ration sur les valeurs de la cl\u00e9 pr\u00e9c\u00e9dente n&rsquo;est plus possible (le code de <code>groupby<\/code> est fait comme \u00e7a).<\/p>\n<p>S&rsquo;il s&rsquo;agissait par contre d&rsquo;utiliser \u00e7a pour it\u00e9rer \u00e0 la vol\u00e9e, \u00e7a serait parfait! Maintenant, \u00e0 vous de voir quelle m\u00e9thode vous convient le mieux.<\/p>\n<blockquote><p>Pour voir ou revoir le tri des listes, <a href=\"http:\/\/saladtomatonion.com\/blog\/2010\/06\/07\/tri-sur-place-de-listes-avec-python\/\" title=\"Tri \u00ab\u00a0sur place\u00a0\u00bb de listes avec python\" target=\"_blank\">c&rsquo;est par ici<\/a>.<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Ajourd&rsquo;hui, on fait des cat\u00e9gories. J&rsquo;ai eu besoin d&rsquo;\u00e9tablir des listes d&rsquo;objets selon un certain crit\u00e8re, et retrouver mes listes par la valeur du crit\u00e8re. Par exemple, dans une liste d&rsquo;objet, grouper les fruits,&#46;&#46;&#46;<\/p>\n","protected":false},"author":2,"featured_media":708,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[4],"tags":[206,229,56,57,21,38],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/saladtomatonion.com\/blog\/wp-content\/uploads\/2011\/04\/python-logo-glassy-small.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/964"}],"collection":[{"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/comments?post=964"}],"version-history":[{"count":16,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/964\/revisions"}],"predecessor-version":[{"id":976,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/964\/revisions\/976"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/media\/708"}],"wp:attachment":[{"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/media?parent=964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/categories?post=964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/tags?post=964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}