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 :

selectionner une partie d'une chaine


Sujet :

Python

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Points : 2
    Points
    2
    Par défaut selectionner une partie d'une chaine
    Bonjour,

    Je cherche à selectionner une partie de chaine qui a cette structure:
    toto[titi].tata.tonton ou tutu.tata.tonton

    Je souhaite récupérer dans les 2 cas toto.tata.tonton et tutu.tata.tonton
    Il faut simplement qu'il supprime [titi] (qui peux etre [tonton] ou autre...)

    J'ai pensé à split mais sans succes... je ne connais pas bien python...

    Merci bcp pour votre aide

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Je ne vois que le module re

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import re
    a="toto[titi].tata.tonton"
    re.sub("\[.*\]", "", a)
    Le résultat est là

    'toto.tata.tonton'
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    magique...

    merci à toi. Je n'avais pas trouvé comment écrire [.*\]...

  4. #4
    Membre habitué Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Points : 190
    Points
    190
    Par défaut
    Juste pour info :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    re.sub("\[.*\]", "", a)
    remplace la première occurrence de n'importe quoi entre crochets par rien dans la chaîne a.
    D'une manière générale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    re.sub("exp", "str", a)
    remplace la première occurrence qui match l'expression régulière exp par la chaîne str dans a.
    (voir ici re.sub)
    [WinXP sp3 / Visual 2005 / Eclipse Ganymede / Python 2.6]
    Hadrien

  5. #5
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Et n'oublie pas le Résolu
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  6. #6
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Je ne vois que le module re
    En fait on peut très bien s'en sortir sans, c'est juste plus long à écrire, je pense même que ce serait plus rapide à éxécuter, mais ce n'est qu'une supposition...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> def delCrochets(txt):
    	levelOpened = 0
    	res         = ''
    	for char in txt:
    		if   char == '['                 : levelOpened += 1
    		elif char == ']' and levelOpened : levelOpened -= 1
    		elif not levelOpened             : res         += char
    		txt = txt[1:]
    	return res
     
    >>> delCrochets('toto[titi].tata.tonton')
    'toto.tata.tonton'

  7. #7
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    J'ai écris une fonction simple en utilisant les index et le slicing

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> def decoupe(string):
    ...     a=string.index("["); b=string.index("]")
    ...     return string[0:a]+string[b+1:len(string)]
     
     
    >>> a
    'toto[titi].tata.tonton'
    >>> decoupe(a)
    'toto.tata.tonton'
    Je pense que ça doit être plus rapide que le module re.

    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Points : 184
    Points
    184
    Par défaut
    @fred1599

    Pas mal comme réponse, j'avais à peu près la même chose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    def decoupe(chaine):
        prefix, rest = chaine.split('[')
        left, suffix = rest.split(']')
        return prefix + suffix
    Mais l'inconvénient de nos méthodes par rapport à celle de N.tox est qu'on l'a dans l'os s'il y a + d'1 paire de [] dans la chaine de caractères.
    Dans mon cas, ça plantera directement à la première ligne, dans le tien, la chaine sortie sera fausse.

    J'aurais aimé savoir si la syntaxe de la chaine à découper était déterminée.

    Et, personnellement, j'essaie de limiter au maximum l'appel au module re, qui est effectivement + lent que les méthodes natives de strings (split, index, etc.).

  9. #9
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Oui c'est vrai, mais dans ce cas, peut-être que le PO pourrait détaillé un peu plus son post, car je ne vois rien de stipuler dans ce sens.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  10. #10
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Tout à fait, je souffre toutefois d'une limitation : si dans la chaine il y a moins de ']' que de '[' après le premier '[', tous les caractères depuis '[' seront ignorés...

    voici une version plus sû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
    23
    24
    25
    >>> txt='1[2[x]3[x[x]x][4'
    >>> def delCrochets(txt):
        res          = ''
        def isThereEnd(s):
            lvl = 0
            for i,char in enumerate(txt[s:]):
                if   char == '['         : lvl += 1
                elif char == ']' and lvl : lvl -= 1
                if not lvl : return i+1
            return 0
        while 1:
            idxs = txt.find('[')
            if idxs==-1: return res+txt
            idxe = isThereEnd(idxs)
            if idxe:
                res += txt[:idxs]
                txt  = txt[idxs+idxe:]
            else :
                idxs = txt.find('[',idxs+1)
                if idxs==-1: return res+txt
                res += txt[:idxs]
                txt  = txt[idxs:]
     
    >>> delCrochets(txt)
    '1[23[4'

  11. #11
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Finalement re est pas si mal
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  12. #12
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    seul problème avec re, c'est qu'il faudrait une regex un peu plus élaboré cause :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> txt='1[x[x]x].2[x].3[4'
    >>> re.sub('\[.*\]','', txt)
    '1.3[4'
    >>> re.sub('\[.*?\]','', txt)
    '1x].2.3[4'
    >>>
    chose dont je suis incapable

  13. #13
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    re est bien quand on connait la forme de la chaine. Mais quand cela devient aléatoire comme dans ton cas, re n'est pas la bonne solution, enfin je pense.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par N.tox Voir le message
    Tout à fait, je souffre toutefois d'une limitation : si dans la chaine il y a moins de ']' que de '[' après le premier '[', tous les caractères depuis '[' seront ignorés...
    En même temps, là, ça commence à devenir compliqué, qu'on choisisse re ou les méthodes des strings.

    Mais on peut toujours blinder le code de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class CrochetsError(Exception): 
        pass
     
    def delCrochets(txt):
        if txt.count('[') != txt.count(']'):
            raise CrochetsError, "Les nombres de crochets ouvrants et de crochets fermants ne correspondent pas."
        # reste du code de la 1° définition de delCrochets
    A la charge de l'appelant de traiter l'exception (ou pas !).

  15. #15
    Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Le module re fait ce qu'il faut. Il peut y avoir effectivement plusieurs crochets dans la phrase mais ne peuvent etre imbriqués... ([to[to]ti] est impossible)

    Merci pour vos messages ça donne des idées...

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par ptidragonbleu Voir le message
    Il peut y avoir effectivement plusieurs crochets dans la phrase mais ne peuvent etre imbriqués... ([to[to]ti] est impossible)
    Si, comme je le suppute, tes chaînes sont en fait des dictionnaires d'objets imbriqués, je te propose de splitter tes chaînes par le délimiteur point, de faire un boucle pour retirer les crochets qui doivent, toujours selon ma suppositon, se trouver en fin de mot et de tout rassembler.

    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
     
    # Si toutes les chaînes possibles respectent ce formalisme
    chaine = 'aaa[bbb].ccc.ddd[eee]'
    liste = []
    for element in chaine.split('.'):
        try:
            element = element[:element.index('[')]
        except ValueError:
            # Pas de '[' dans l'élément, on continue.
            pass
        liste.append(element)
    resultat = '.'.join(liste)
     
    # En 1 ligne, mais je trouve un peu moins lisible, à cause du split()[]
    '.'.join(c.split('[')[0] for c in chaine.split('.'))

  17. #17
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    même si cette méthode (en une ligne) implique plusieurs parcours de chaines, cela reste la plus rapide. Je suppose que cela est du au fait que split soit écrit et optimisé en C. Ma première méthode quand à elle est loin derrière (même sans redéfinition constante de txt). Si la structure de ton texte obéit donc aux conditions ennoncées par nardo47, alors sa méthode est carrément la plus appropriée.

    chaine testée 5000 fois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    txt = ''.join(['%s[xxx]'%hex(x) for x in xrange(100)])
    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
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    6.444    6.444 <string>:1(<module>)
            1    0.000    0.000    6.443    6.443 crochets.py:1(<module>)
         5000    0.863    0.000    0.863    0.000 crochets.py:1(me1)
       500000    1.806    0.000    1.806    0.000 crochets.py:12(isThereEnd)
         5000    2.534    0.001    5.362    0.001 crochets.py:20(me2)
         5000    0.035    0.000    0.180    0.000 crochets.py:35(nardo)
        10000    0.042    0.000    0.087    0.000 crochets.py:36(<genexpr>)
            1    0.037    0.037    6.443    6.443 crochets.py:39(main)
            1    0.001    0.001    6.444    6.444 {execfile}
          100    0.000    0.000    0.000    0.000 {hex}
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Prof
    iler' objects}
       505000    1.023    0.000    1.023    0.000 {method 'find' of 'str' objects}
         5001    0.044    0.000    0.131    0.000 {method 'join' of 'str' objects}
        10000    0.060    0.000    0.060    0.000 {method 'split' of 'str' objects}
    Si ma dernière méthode possède un equivalent regex, alors re resterait sûrement préférable.

  18. #18
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Points : 184
    Points
    184
    Par défaut
    Citation Envoyé par N.tox Voir le message
    même si cette méthode (en une ligne) implique plusieurs parcours de chaines, cela reste la plus rapide. Je suppose que cela est du au fait que split soit écrit et optimisé en C.
    En partie. C'est aussi le cas du join mais surtout du générateur (l'expression (f(x) for x in A)).
    Celui-ci ne génère chaque élément de la liste utilisée par join à la demande, ce qui m'évite de construire une liste complète, puis de la parcourir en entier avec join.
    Qui plus est, l'implémentation d'un générateur (et d'une compréhension de liste, c'est à dire la même chose avec des crochets) est optimisée et plus rapide qu'une boucle for classique (en + de prendre moins de place et d'être + naturel à comprendre).

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/04/2013, 15h57
  2. [RegEx] Retourner une array sur une partie de la chaine
    Par absurdsystem dans le forum Langage
    Réponses: 2
    Dernier message: 25/04/2010, 16h03
  3. Sélectionner seulement une partie d'une valeur d'une cellule
    Par ArthurO0O dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 20/08/2007, 11h05
  4. masquer une partie d'une vidéo par une banniere
    Par lezabour dans le forum Général Conception Web
    Réponses: 1
    Dernier message: 16/10/2006, 16h47
  5. copier une partie d'une image vers une autre
    Par gregcat dans le forum Langage
    Réponses: 1
    Dernier message: 14/04/2006, 13h39

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