{"id":305,"date":"2010-06-07T17:15:36","date_gmt":"2010-06-07T16:15:36","guid":{"rendered":"http:\/\/saladtomatonion.com\/blog\/?p=305"},"modified":"2010-06-07T17:15:36","modified_gmt":"2010-06-07T16:15:36","slug":"tri-sur-place-de-listes-avec-python","status":"publish","type":"post","link":"https:\/\/saladtomatonion.com\/blog\/2010\/06\/07\/tri-sur-place-de-listes-avec-python\/","title":{"rendered":"Tri \u00ab\u00a0sur place\u00a0\u00bb de listes avec python"},"content":{"rendered":"<p>Je n&rsquo;en avais jamais eu l&rsquo;utilit\u00e9 jusqu&rsquo;\u00e0 pr\u00e9sent, et ce n&rsquo;est donc que r\u00e9cemment que j&rsquo;ai d\u00e9couvert le tri de listes de python. \u00c7a marche vite et bien, avec du code compact!<br \/>\n<!--more--><\/p>\n<p>Le prototype de la m\u00e9thode est <code>list.sort([cmp[, key[, reverse]]])<\/code> :<\/p>\n<ul>\n<li>sans argument, la m\u00e9thode tente d&rsquo;utiliser les op\u00e9rateurs de comparaison impl\u00e9ment\u00e9s dans les objets de la liste.<\/li>\n<li><strong>cmp <\/strong>: une fonction prenant deux arguments et qui retourne 0, -1, ou 1 selon que le premier argument est consid\u00e9r\u00e9 inf\u00e9rieur, \u00e9gal ou sup\u00e9rieur au deuxi\u00e8me argument<\/li>\n<li><strong>key<\/strong>: une fonction qui prend un objet en argument et qui renvoie un champ cl\u00e9 sur lequel on souhaite classer. Sort utilise cette cl\u00e9 pour le tri en utilisant les comparaisons intrins\u00e8ques de la cl\u00e9.<\/li>\n<li><strong>reverse<\/strong>: un bool\u00e9en qui permet un classement invers\u00e9. Il est <code>False<\/code> par d\u00e9faut.<\/li>\n<\/ul>\n<p>Pour des objets \u00e9labor\u00e9s (par exemple, des performances de saut en longueur, qui contiennent la date, la longueur et le sportif), on peut avoir impl\u00e9ment\u00e9 les op\u00e9rateurs <code>__cmp__<\/code>, <code>__eq__<\/code> ou <code>__ne__<\/code> , pour que le sort les utilise automatiquement (comparaison par date puis par longueur sur notre exemple).<\/p>\n<p>Mais il arrive que ces op\u00e9rateurs de comparaison n&rsquo;aient pas vraiment de sens, dans mon cas, des objets repr\u00e9sentant des enregistrements, que je souhaite classer par id. Ici, comparer intrins\u00e8quement deux objets ne veut pas dire grand chose.<\/p>\n<p>Je pourrais alors proc\u00e9der comme suit :<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">\r\n# ma fonction qui donne la cl\u00e9\r\ndef get_key_for_object(obj):\r\n    return obj.id\r\n\r\n# je r\u00e9cup\u00e8re mes objets\r\nmaListe = get_records()\r\n# je classe\r\nmaListe.sort(key=get_key_for_object)\r\n<\/pre>\n<p>On remarque que la fonction get_key_for_object est vraiment tr\u00e8s simple : on remplace la d\u00e9finition de la fonction par une simple fonction <em>lambda<\/em> dans l&rsquo;appel du sort.<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">\r\nmaListe.sort(key=lamba obj: obj.id)\r\n<\/pre>\n<p>Je peux m\u00eame trier des objets h\u00e9t\u00e9roclites du moment qu&rsquo;ils aient bien tous la propri\u00e9t\u00e9 <code>id<\/code>!<\/p>\n<p>Sur le m\u00eame principe, je peux d\u00e9finir une fonction cmp. Imaginons que je veuille classer des nombres complexes en fonction de leur module, je pourrais faire ceci :<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">\r\ndef compare_magnitudes(a,b):\r\n    a_m = sqrt(a.real*a.real + a.im*a.im)\r\n    b_m = sqrt(b.real*b.real + b.im*b.im)\r\n    # il ne reste plus qu'\u00e0 comparer deux float\r\n    return cmp(a_m, b_m)\r\n\r\nmesComplexes.sort(cmp=compare_magnitudes)\r\n<\/pre>\n<p>Encore plus simplement, si mes complexes definissaient un propri\u00e9t\u00e9 magnitude:<\/p>\n<pre name=\"code\" class=\"py:nogutter:nocontrols\">\r\nmesComplexes.sort(cmp=lambda a,b: cmp(a.magnitude, b.magnitude))\r\n<\/pre>\n<p>Tout \u00e7a est donc bien pratique lorsque nos objets ne d\u00e9finissent pas d&rsquo;op\u00e9rateurs de comparaison, ou bien que l&rsquo;on souhaite ponctuellement d\u00e9finir un type de tri sp\u00e9cifique.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Je n&rsquo;en avais jamais eu l&rsquo;utilit\u00e9 jusqu&rsquo;\u00e0 pr\u00e9sent, et ce n&rsquo;est donc que r\u00e9cemment que j&rsquo;ai d\u00e9couvert le tri de listes de python. \u00c7a marche vite et bien, avec du code compact!<\/p>\n","protected":false},"author":2,"featured_media":0,"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":[58,61,62,56,57,21,38,60,59],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/305"}],"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=305"}],"version-history":[{"count":14,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/305\/revisions"}],"predecessor-version":[{"id":319,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/305\/revisions\/319"}],"wp:attachment":[{"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/media?parent=305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/categories?post=305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/tags?post=305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}