IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Logique/algorithme et rechercher-remplacer avec des "chaînes soeurs"


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 24
    Points : 25
    Points
    25
    Par défaut Logique/algorithme et rechercher-remplacer avec des "chaînes soeurs"
    Bonsoir,

    Je suis actuellement confronté à un problème dont j'ai dû mal à trouver la solution même théorique.

    Mon cas de figure est le suivant :

    Je cherche à remplacer des chaînes par ces mêmes chaînes avec des guillemets en plus.
    Pour cela, j'ai constitué un ""dictionnaire" en découpant mes chaînes par mots et en supprimant les doublons.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    import sys, string
     
    ma_chaine_initiale="azerty uiop. (azerty) (uiop )ytreza qsdfg. hjklm)) (azertyyio.uiop) azertyy uiop ytreza qsdfgj hjklml"
     
    #J'obtiens un dictionnaire comme ci-dessous
     
    ma_liste_dict = ['azerty','uiop','ytreza','qsdfg','hjklm','azertyyio','azertyy','ytreza','qsdfgj','hjklml']
     
    for item in ma_liste_dict:
        ma_chaine_initiale = string.replace(ma_chaine_initiale,item,'"' + item + '"')           
    print ma_chaine_initiale
    J'obtiens un beau résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    "azerty" "uiop". ("azerty") ("uiop" )""ytreza"" "qsdfg". "hjklm")) ("azerty"yio.
    "uiop") "azerty"y "uiop" ""ytreza"" "qsdfg"j "hjklm"l
    Pour comprendre ce cas, je vais prendre le cas de la chaine azertyyio.

    Dans ma boucle "for item in ma_liste_dict:", le rechercher-remplacer sur azertyyio me renvoie "azerty"yio car il a d'abord recherché sur azerty et à remplacé la chaine.
    J'ai pensé solutionné le problème, en rangeant par ordre décroissant de longueur les chaînes du dictionnaire avec
    ma_liste_dict = sorted(ma_liste_dict, key=len, reverse=True)

    Bilan : il m'imbrique sur la chaîne azertyyio au fil de la boucle car les trois élements du rechercher-remplacer partage la même chaîne azerty
    1er tour
    "azertyyio"
    2ème tour
    ""azertyy"io"
    enfin 3ème tour
    """azertyy"io""

    Il me faut une variable de contrôle pour dire à mon rechercher-remplacer de ne plus travailler là où il est déjà passé (il fait du zèle...). Vous auriez une idée comment procéder ? D'autres solutions alternatives pour résoudre un cas d'utilisation similaire au mien? Existe-t-il un algorithme pour ce cas ?

    Merci de vos remarques (constructives bien entendues )

    gratiert

    Merci

  2. #2
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Cela pourrait-il faire ton affaire ?
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    def clean(s):
        L=[x for x in s if x.isalpha()]
        return ''.join(L)
     
    ma_chaine_initiale="azerty uiop. (azerty) (uiop )ytreza qsdfg. hjklm)) (azertyyio.uiop) azertyy uiop ytreza qsdfgj hjklml"
    dic=ma_chaine_initiale.rsplit(' ')
    dic=[clean(s) for s in dic]
    dic=['"'+item+'"' for item in dic]
    print dic

  3. #3
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Le problème se pose parce que replace() cherche et remplace partout dans la chaîne.

    Il me faut une variable de contrôle pour dire à mon rechercher-remplacer de ne plus travailler là où il est déjà passé (il fait du zèle...).
    Corriger quelque chose qui n’est dès le départ pas adapté à l’objectif -> mauvaise piste.

    Faire comme Zavonen, abandonner replace() -> bonne piste.
    Mais qu’est ce qu’on fait après avec la liste obtenue ? Tous les autres signes que blanc et lettres ont disparu. Comment fait on pour obtenir la chaîne initiale additionnée de guillemets aux bons endroits ?



    Au fait, pourquoi appeler dictionnaire ce qui est une liste ?? Et employer dic ou dict dans son nom ?



    Je pense qu’il y a deux sortes de méthodes pour faire ce genre de traitement de mots dans une chaîne:

    - une fonction génératrice pour traiter chaque début ou fin de mot différemment des autres caractères

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ma_chaine_initiale="azerty uiop. (azerty) (uiop )ytreza qsdfg. hjklm)) (azertyyio.uiop) "\
                        "azertyy uiop ytreza qsdfgj hjklml"
     
    def gen_guillemette(s,separateurs):
        if s[0] not in separateurs:  yield '"'
        s, what = s + separateurs[0], ('','"')
        sig = [ 1 if c in separateurs else 0 for c in s ]
        for i in xrange(len(s)-1):
            yield s[i] + what[(sig[i] + sig[i+1])%2]
     
    print '~~~~ separateurs: blancs et .()'
    for machaine in ('le pont Alexandre II','.kilo verdure','.(henri troyat)',
                     '..cvfd loup..)',' sentinelle adam ',
                     ma_chaine_initiale):
        print '\n' + machaine + ''.join( gen_guillemette(machaine,' .()') )

    - une expression régulière:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import re
     
    def re_guillemette(s,separateurs):
        RE = '([^' + ''.join(x for x in separateurs) + ']+)'
        return '"'.join(re.split(RE,s))
     
    machaine = 'le pont Alexandre II'
    print '\n' + machaine + '~~~~ separateurs : blanc et .()'+\
          re_guillemette(machaine, ' .()' ) + '\n'
     
    machaine = '.kilo verdure ronflement'
    print '\n' + machaine + '~~~~ separateurs : blanc et )(.r'+\
          re_guillemette(machaine, [' ',')','(','.','r'] ) + '\n'
     
    machaine = '.(cool balon  ovale)'
    print '\n' + machaine + '~~~~ separateurs : o'+\
          re_guillemette(machaine, ('o',) ) + '\n'
     
    ma_chaine_initiale="azerty uiop. (azerty) (uiop )ytreza qsdfg. hjklm)) (azertyyio.uiop) "\
                        "azertyy uiop ytreza qsdfgj hjklml"
    print '\n' + machaine + '~~~~ separateurs : blanc et .()'+\
          re_guillemette(ma_chaine_initiale, ' .()' ) + '\n'

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 24
    Points : 25
    Points
    25
    Par défaut
    Bonjour,

    D'abord, merci pour vos réponses.

    Pour mon nom de variable, j'utilisais dic car je considérais mon contenu et pas la structure qui contient le contenu (une liste donc )
    Contrairement à votre manière de faire qui est d'utiliser une liste dans un liste ma logique était dans le "replace" (que vous m'avez démontré comme un mauvais raisonnement pour mon cas de figure) et je considérais que d'un côté, j'allais alimenter une base et de l'autre côté lancer-un rechercher-remplacer depuis cette base (que je qualifiais ainsi de dictionnaire).
    En regardant dans la documentation python, j'ai compris pourquoi l'appellation dictionnaire vous gênait (en terme de structure, cela a un autre sens que le sens commun que j'ai utilisé dans mon exemple)

    J'avais commencé à partir de la solution de Zavonen en changeant son split et en utilisant une expression régulière pour récupérer les chaînes complètes de texte et en incluant aussi celle qui servait de séparateur.
    re.split('([\W]+)', ma_chaine_initiale)
    Il me restait encore à utiliser une fonction dérivée de clean pour substituer les chaînes alphanumériques.
    A la fin, j'avais préparé un fonction join() pour réunir les éléments de la liste (chaines remplacées par celles avec guillemets + les autres chaînes non remplacées constituées des différents séparateurs)

    Mon raisonnement se rapprochait du 2ème que vous avez proposé mais sans la concision

    Cordialement

    gratiert,
    débutant python

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 369
    Points : 36 908
    Points
    36 908
    Par défaut mots -> tokens -> mots.
    Salut,
    L'idée qui me viendrait serait plutôt d'analyser la suite de mots initiale pour la transformer en une liste de 'tokens'. Ceux-ci pouvant être des entiers mais aussi l'instance d'une classe représentant le "mot".
    i.e. à partir d'un texte "suite de mots" : m1 m2 m3 m4
    j'obtiens une liste d'instances [ token(m1), token(m2), token(m3), token(m4) ] qui représente la suite des mots du texte.
    En faisant l'impasse sur la non représentation des espace et autres ponctuations on peut reconstruire le 'texte' initial.

    Token est un "Flyweight" i.e si mot1 == mot2 alors Token(mot1) is Token(mot2) Reste à 'marquer' les mots à décorer de """.

    FlyWeight pourrait être réalisé de la façon suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    class Token(object):
         _mots_ = {}
         def __new__(cls, mot):
              if mot not in cls._mots_:
                    token = object.__new__(cls)
                    token.__init__(mot)
                    cls._mots_[mot] = token
              return cls._mots_[mot]
     
         def __init__(self, mot):
              self._mot = mot
     
         def __str__(self):
              return self._mot
     
    class Decorated(Token):
     
         def __init__(self, mot):
            super(Decorated, self).__init__(mot)
         def __str__(self):
            return '"%s"' % self._mot
     
    decorate = ( 'm2', 'm3',' m6')
    text = 'm2 m3 m2 m7 m6'
    tkList = []
    for w in text.split(' '):
        if w in decorate:
            tkList.append(Decorated(w))
        else:
            tkList.append(Token(w))
     
    for tk in tkList:
        print str(tk),
    Note: Dans ce cas, on a la liste de mots à décorer 'au début' et on ajoute Token(m1) ou Decorated(m1) dans la liste suivant le cas.

    Mais je reconnais que cela n'est pas très conventionnel.
    - W

Discussions similaires

  1. [Yahoo UI] AutoComplete avec Recherche multiple avec des remote data
    Par kaboume dans le forum Bibliothèques & Frameworks
    Réponses: 2
    Dernier message: 03/04/2009, 14h42
  2. [RegEx] Rechercher/remplacer avec preg_replace
    Par olbouss dans le forum Langage
    Réponses: 5
    Dernier message: 13/01/2009, 12h00
  3. [RegEx] Ereg() recherche chaine avec des ()
    Par PsYKrO dans le forum Langage
    Réponses: 1
    Dernier message: 16/04/2008, 22h58
  4. [VS] rechercher/remplacer avec des regexp
    Par v1nce dans le forum Visual Studio
    Réponses: 4
    Dernier message: 03/07/2007, 14h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo