SaladTomatOnion Le blog qui mange trois fruits et légumes

10Juil/120

Substitution de chaînes de caractères par dictionnaire, en 3 lignes

Aujourd'hui, une petite recette de python que j'ai concoctée pour un besoin très précis. Il s'agit de recevoir une chaîne de caractère, voir si elle contient la chaîne à remplacer en regardant dans un dictionnaire, puis à faire le remplacement. En l'occurence, il s'agit de toujours remplacer le début de la chaîne de caractères.

J'ai donc un dictionnaire de substitution que j'appelle subst_map qui contient en clé l'élément à retrouver, et en valeur la chaîne de remplacement. Une contrainte supplémentaire est de prendre la correspondance la plus longue, si certaines clés commencent de la même façon.

La méthode la plus évidente est de faire une boucle:

def substitute(input, subst_map):
    chosen_key = None
    for k in subst_map.keys():
        if input.startswith(k):
            if chosen_key is None or len(k) > len(chosen_key):
                chosen_key = k
    # Le dernier argument de replace() sert à limiter
    # le nombre de remplacements
    return input.replace(chosen_key, subst_map[chosen_key], 1)

Et cette méthode fonctionne très bien. Cependant, on peut arriver au même résultat avec très peu de code.

def substitute(input, subst_map):
    keys = filter(lambda s: input.startswith(s), subst_map.keys())
    keys.sort(key=lambda v: len(v), reverse=True)
    if keys: #si la longueur > 0, j'ai une correspondance
        # et je prends la première
        return input.replace(keys[0], subst_map[keys[0]], 1)
    else: return input

Et c'est tout!

La fonction filter fait la même chose que ma boucle, mais la condition de filtrage est directement passée comme une fonction anonyme (une lambda). De la même façon, je trie à la volée les clés trouvées par ordre de longueur croissante, pour utiliser la première.

Le code n'est pas forcément plus rapide à l'exécution, mais il est bien plus rapide à écrire, et assez compréhensible. J'aurais même pu faire le filtrage et le tri sur une seule ligne, mais ça aurait été pour le coup plus compliqué à lire.

Commentaires (0) Trackbacks (0)

Aucun commentaire pour l'instant


Laisser un commentaire

Aucun trackbacks pour l'instant

Afficher les boutons de partage
Masquer les boutons de partage