{"id":861,"date":"2012-07-10T15:21:12","date_gmt":"2012-07-10T13:21:12","guid":{"rendered":"http:\/\/saladtomatonion.com\/blog\/?p=861"},"modified":"2012-07-10T15:41:03","modified_gmt":"2012-07-10T13:41:03","slug":"substitution-de-chaines-de-caracteres-par-dictionnaire-en-3-lignes","status":"publish","type":"post","link":"https:\/\/saladtomatonion.com\/blog\/2012\/07\/10\/substitution-de-chaines-de-caracteres-par-dictionnaire-en-3-lignes\/","title":{"rendered":"Substitution de cha\u00eenes de caract\u00e8res par dictionnaire, en 3 lignes"},"content":{"rendered":"<p>Aujourd&rsquo;hui, une petite recette de <a href=\"http:\/\/python.org\/\" target=\"_blank\">python<\/a> que j&rsquo;ai concoct\u00e9e pour un besoin tr\u00e8s pr\u00e9cis. Il s&rsquo;agit de recevoir une cha\u00eene de caract\u00e8re, voir si elle contient la cha\u00eene \u00e0 remplacer en regardant dans un dictionnaire, puis \u00e0 faire le remplacement. En l&rsquo;occurence, il s&rsquo;agit de toujours remplacer le d\u00e9but de la cha\u00eene de caract\u00e8res.<!--more--><\/p>\n<p>J&rsquo;ai donc un dictionnaire de substitution que j&rsquo;appelle <code>subst_map<\/code> qui contient en cl\u00e9 l&rsquo;\u00e9l\u00e9ment \u00e0 retrouver, et en valeur la cha\u00eene de remplacement. Une contrainte suppl\u00e9mentaire est de prendre la correspondance la plus longue, si certaines cl\u00e9s commencent de la m\u00eame fa\u00e7on.<\/p>\n<p>La m\u00e9thode la plus \u00e9vidente est de faire une boucle:<\/p>\n<pre  name=\"code\" class=\"py:nogutter:nocontrols\">\r\ndef substitute(input, subst_map):\r\n    chosen_key = None\r\n    for k in subst_map.keys():\r\n        if input.startswith(k):\r\n            if chosen_key is None or len(k) > len(chosen_key):\r\n                chosen_key = k\r\n    # Le dernier argument de replace() sert \u00e0 limiter\r\n    # le nombre de remplacements\r\n    return input.replace(chosen_key, subst_map[chosen_key], 1)\r\n<\/pre>\n<p>Et cette m\u00e9thode fonctionne tr\u00e8s bien. Cependant, on peut arriver au m\u00eame r\u00e9sultat avec tr\u00e8s peu de code.<\/p>\n<pre  name=\"code\" class=\"py:nogutter:nocontrols\">\r\ndef substitute(input, subst_map):\r\n    keys = filter(lambda s: input.startswith(s), subst_map.keys())\r\n    keys.sort(key=lambda v: len(v), reverse=True)\r\n    if keys: #si la longueur > 0, j'ai une correspondance\r\n        # et je prends la premi\u00e8re\r\n        return input.replace(keys[0], subst_map[keys[0]], 1)\r\n    else: return input\r\n<\/pre>\n<p>Et c&rsquo;est tout!<\/p>\n<p>La fonction <code>filter<\/code> fait la m\u00eame chose que ma boucle, mais la condition de filtrage est directement pass\u00e9e comme une fonction anonyme (une <a href=\"http:\/\/docs.python.org\/reference\/expressions.html#lambda\" target=_blank>lambda<\/a>). De la m\u00eame fa\u00e7on, je trie \u00e0 la vol\u00e9e les cl\u00e9s trouv\u00e9es par ordre de longueur croissante, pour utiliser la premi\u00e8re.<\/p>\n<p>Le code n&rsquo;est pas forc\u00e9ment plus rapide \u00e0 l&rsquo;ex\u00e9cution, mais il est bien plus rapide \u00e0 \u00e9crire, et assez compr\u00e9hensible. J&rsquo;aurais m\u00eame pu faire le filtrage et le tri sur une seule ligne, mais \u00e7a aurait \u00e9t\u00e9 pour le coup plus compliqu\u00e9 \u00e0 lire.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aujourd&rsquo;hui, une petite recette de python que j&rsquo;ai concoct\u00e9e pour un besoin tr\u00e8s pr\u00e9cis. Il s&rsquo;agit de recevoir une cha\u00eene de caract\u00e8re, voir si elle contient la cha\u00eene \u00e0 remplacer en regardant dans un&#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,207,205,21,38,60,203,204],"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\/861"}],"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=861"}],"version-history":[{"count":17,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/861\/revisions"}],"predecessor-version":[{"id":893,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/posts\/861\/revisions\/893"}],"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=861"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/categories?post=861"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/saladtomatonion.com\/blog\/wp-json\/wp\/v2\/tags?post=861"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}