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 :

Travail sur des Strings


Sujet :

Python

  1. #1
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut Travail sur des Strings
    Bonjour,

    Je suis débutant en Python et j'aimerais essayer de faire des modifications sur des chaines de caractères. Par exemple avec une chaine de départ comme celle-ci :
    "(5, A, 2), (3, B, 4)"
    Je voudrais générer les chaines suivantes (en appliquant + ou - 1 sur chacune des valeurs numériques, et en traitant tous les cas possibles).

    "(4, A, 1), (3, B, 4)"
    "(4, A, 2), (3, B, 4)"
    "(4, A, 3), (3, B, 4)"
    "(5, A, 1), (3, B, 4)"
    "(5, A, 3), (3, B, 4)"
    "(6, A, 1), (3, B, 4)"
    "(6, A, 2), (3, B, 4)"
    "(6, A, 3), (3, B, 4)"

    "(5, A, 2), (2, B, 3)"
    "(5, A, 2), (2, B, 4)"
    "(5, A, 2), (2, B, 5)"
    "(5, A, 2), (3, B, 3)"
    "(5, A, 2), (3, B, 5)"
    "(5, A, 2), (4, B, 3)"
    "(5, A, 2), (4, B, 4)"
    "(5, A, 2), (4, B, 5)"

    "(4, A, 1), (2, B, 3)"
    "(4, A, 1), (2, B, 4)"
    "(4, A, 1), (2, B, 5)"
    "(4, A, 1), (3, B, 3)"
    "(4, A, 1), (3, B, 5)"
    "(4, A, 1), (4, B, 3)"
    "(4, A, 1), (4, B, 4)"
    "(4, A, 1), (4, B, 5)"

    "(4, A, 3), (2, B, 3)"
    "(4, A, 3), (2, B, 4)"
    "(4, A, 3), (2, B, 5)"
    "(4, A, 3), (3, B, 3)"
    "(4, A, 3), (3, B, 5)"
    "(4, A, 3), (4, B, 3)"
    "(4, A, 3), (4, B, 4)"
    "(4, A, 3), (4, B, 5)"

    "(5, A, 1), (2, B, 3)"
    etc...



    L'idéal serait que ce soit appliquable sur une chaine de départ de longueur variable (avec un nombre non défini d'éléments, un élément étant '(nombre, lettre, nombre)'). Ce n'est pas une erreur je veux bien travailler sur des chaines.

    Pourriez vous m'aiguillez sur comment réaliser celà, car j'ai vu qu'en python on peut faire les choses très simplement en très peu de lignes !
    Désolé si l'exemple est un peu long.

    Pingvince

  2. #2
    Expert éminent sénior
    Avatar de Guigui_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 864
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2002
    Messages : 1 864
    Points : 10 067
    Points
    10 067
    Par défaut
    pour manipuler les string: http://python.developpez.com/faq/?page=String
    Ensuite, tes nombres et lettres sont toujours à la même position (position: 1, 4, 7, 12, 15, 18, 23, ... (suite qu'il facile de générer dans une boucle for).
    ensuite
    Pour savoir si tu une chaine ou un caractère est un nombre, applique la fonction isdigit()
    => => pour convertir un string en int => int(monstring)
    ...

  3. #3
    Membre expérimenté Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Points : 1 728
    Points
    1 728
    Par défaut
    Bonjour,

    tu peux aussi utiliser les fonctionnalités de formatage de chaîne:
    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
    import string
     
    chaine = "(5, A, 2), (3, B, 4)" # chaine initiale
    values = [] # liste des valeurs de depart
    liste = [] # liste temporaire
     
    for car in chaine:
        if car in string.letters or car in string.digits:
            liste.append('%s')
            values.append(car)
        else:
            liste.append(car)
     
    chaine = "".join(liste)
     
    # la chaine avec les caracteres de formatage
    print chaine
    # (%s, %s, %s), (%s, %s, %s)
    # exemple d'utilisation
    print chaine % tuple([chr(ord(car) +1) for car in values])
    # (6, B, 3), (4, C, 5)
    Il te reste à créer les fonctions pour modifier la liste des valeurs.

    Bon python.
    "Etre conscient de la difficulté permet de l'éviter.."
    Lao-Tseu.

  4. #4
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses.

    Pour Guigui_, je veux bien travailler sur des chaines, donc mes indices seraient 1, 12, etc...

    Avec vos 2 propositions, je risque aussi d'avoir des problèmes si ma chaine de départ est "(5, A, 222), (3, B, 4)" car dans ce cas je ne pourrais pas retrouver mes 2 nombres 222 et 3 pour leur appliquer + et - 1, ou je me trompe ?

    PS. Les lettres restent les mêmes.
    Et oui il va falloir que je fasse des fonctions pour être sûr d'avoir traité tous les cas possibles !

    J'ai modifié ton code pacificator et j'ai un peu avancé.

    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    import string
     
    chaine = "(5, A, 8)" # chaine initiale
    values = [] # liste des valeurs de depart
    liste = [] # liste temporaire
     
    for car in chaine:
        if car in string.digits:
            liste.append('%s')
            values.append(car)
        else:
            liste.append(car)
     
    chaine = "".join(liste)
     
    # la chaine avec les caracteres de formatage
    print "Chaine avec caractere de formatage =", chaine
    # Chaine avec caractere de formatage = (%s, A, %s)
    # exemple d'utilisation
    listAll = []
    listNewNb = []
    for nb in values:
        listNewNb.append(int(nb) -1)
        listNewNb.append(int(nb))
        listNewNb.append(int(nb) +1)
        listAll.append(listNewNb)
        listNewNb = []
     
    print "listAll=", listAll
    #listAll= [[4, 5, 6], [7, 8, 9]]
     
    firstFlag = True
    firstSet = []
    for listNewNb in listAll:
        if not firstFlag:
    	for nb in firstSet:
    	    print chaine % tuple([nb, listNewNb[0]])
    	    print chaine % tuple([nb, listNewNb[1]])
    	    print chaine % tuple([nb, listNewNb[2]])
    	    firstFlag = True
        else:
    	firstSet = listNewNb
    	firstFlag = False
    Et j'obtiens :
    (4, A, 7)
    (4, A, 8)
    (4, A, 9)
    (5, A, 7)
    (5, A, 8)
    (5, A, 9)
    (6, A, 7)
    (6, A, 8)
    (6, A, 9)

    (Bon j'ai encore le (5, A, 8) en trop mais c'est pas dur de l'enlever je pense). Je continue donc là dessus pour essayer que cela marche aussi avec une chaine de départ de 2 éléments (ou plus) mais ca m'a l'air déjà beaucoup plus compliqué ! Si vous avez quelques conseils je les prends !

  5. #5
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    J'arrive à obtenir quelque chose comme celà :

    Ma liste de valeurs possibles: listAll= [[4, 5, 6], [7, 8, 9], [2, 3, 4], [3, 4, 5]]
    Avec les lettres correspondantes: listLetters: ['A', 'B']

    Et j'arrive à générer les éléments séparéments comme ceci:
    (4, A, 7)
    (4, A, 8)
    (4, A, 9)
    (5, A, 7)
    (5, A, 8)
    (5, A, 9)
    (6, A, 7)
    (6, A, 8)
    (6, A, 9)
    (2, B, 3)
    (2, B, 4)
    (2, B, 5)
    (3, B, 3)
    (3, B, 4)
    (3, B, 5)
    (4, B, 3)
    (4, B, 4)
    (4, B, 5)


    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    import string
     
    chaine = "(5, A, 8), (3, B, 4)" # chaine initiale
    values = [] # liste des valeurs de depart
    liste = [] # liste temporaire
    listLetters = []
     
    chaines = chaine.split("), (")
    chaines[0] = chaines[0].strip('(')
    chaines[-1] = chaines[-1].strip(')')
    print chaines
    #['5, A, 8', '3, B, 4']
     
     
    for chaine in chaines:
        for car in chaine:
            if car in string.digits:
                liste.append('%s')
                values.append(car)
            else:
                liste.append(car)
    	    if str(car).isalpha():
    		listLetters.append(car)
     
        liste.append(', ')
        chaine = "".join(liste)
    chaine.strip(", ")
    print chaine
    # %s, A, %s, %s, B, %s, 
     
    print "listLetters=", listLetters
    #['A', 'B']
     
     
     
    # exemple d'utilisation
    listAll = []
    listNewNb = []
    for nb in values:
        listNewNb.append(int(nb) -1)
        listNewNb.append(int(nb))
        listNewNb.append(int(nb) +1)
        listAll.append(listNewNb)
        listNewNb = []
     
    print "listAll=", listAll
    #listAll= [[4, 5, 6], [7, 8, 9], [2, 3, 4], [3, 4, 5]]
     
     
    chaineFormatee = "(%s, %s, %s)"
    firstFlag = True
    firstSet = []
    indLetter = 0
    compteLetter = 0
    for idx,listNewNb in enumerate(listAll):
        if not firstFlag:
    	for nb in firstSet:
    	    print chaineFormatee % tuple([nb, listLetters[indLetter],listNewNb[0]])
    	    print chaineFormatee % tuple([nb, listLetters[indLetter],listNewNb[1]])
    	    print chaineFormatee % tuple([nb, listLetters[indLetter],listNewNb[2]])
    	    compteLetter = compteLetter +1
    	    if compteLetter == 3:
     	        indLetter = indLetter+1
    		compteLetter = 0
    	    firstFlag = True
    	    firstSet = []
        else:
    	firstSet = listNewNb
    	firstFlag = False
    Comment à partir de celà puis-je générer toutes mes chaines comme dans mon 1er exemple ? Suis-je sur la bonne voix ou pas ?

    Et comment puis -je généraliser ce cas, pour que cela marche avec des chaines de départ de longueur différentes : "(5, A, 8)" ou "(5, A, 8), (3, B, 4)" ou "(5, A, 8), (3, B, 4), (7, C, 2)" ?

  6. #6
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut Nouvelle question sur les strings: optimisation
    Bonjour,
    J'ai une question du même genre sur les chaînes. Je veux récupérer les nombres qui se trouvent dans un texte. Mais seulement ceux qui sont derrière un '#'.
    J'ai fait ceci qui fonctionne, mais je voudrais savoir si je peux l'améliorer, car je fais ceci dans de très longues boucles et ca prend beaucoup de temps à s'exécuter.

    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
    import string
     
    description = "Ticket Id=120, Owner=tgor3401, Time=2006-09-08 16:14:20, Desc=SVNng short of a r=tgor3401, time=26:19:52 code. #124 #125 #126.Ticket 120 author=tgor3401, time=2006-09-15 15:19:21, , newvalue=closed. (#98) Ticket 120 author=tgor3401t.."
     
    strT = description + " "
    posB=0
    strSearchTicket = "#"
    posA = strT.find(strSearchTicket)
    strTemp = ""
    while posA !=-1:
      strT = strT[posA+1:]
      posB = 0
      while strT[posB].isdigit():
        posB = posB +1
      strTemp = strT[:posB]
      if (strTemp) :
        print strTemp
      strT = strT[posB:]
      posA = strT.find(strSearchTicket)
     
    #124
    #125
    #126
    #98

  7. #7
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Citation Envoyé par Pingvince Voir le message
    Bonjour,
    J'ai une question du même genre sur les chaînes. Je veux récupérer les nombres qui se trouvent dans un texte. Mais seulement ceux qui sont derrière un '#'.
    J'ai fait ceci qui fonctionne, mais je voudrais savoir si je peux l'améliorer, car je fais ceci dans de très longues boucles et ca prend beaucoup de temps à s'exécuter.

    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
    import string
     
    description = "Ticket Id=120, Owner=tgor3401, Time=2006-09-08 16:14:20, Desc=SVNng short of a r=tgor3401, time=26:19:52 code. #124 #125 #126.Ticket 120 author=tgor3401, time=2006-09-15 15:19:21, , newvalue=closed. (#98) Ticket 120 author=tgor3401t.."
     
    strT = description + " "
    posB=0
    strSearchTicket = "#"
    posA = strT.find(strSearchTicket)
    strTemp = ""
    while posA !=-1:
      strT = strT[posA+1:]
      posB = 0
      while strT[posB].isdigit():
        posB = posB +1
      strTemp = strT[:posB]
      if (strTemp) :
        print strTemp
      strT = strT[posB:]
      posA = strT.find(strSearchTicket)
     
    #124
    #125
    #126
    #98
    Je ne sais pas si ça va être plus rapide, mais c'est bien compliqué, votre truc.
    Avec des regex (import re) la réponse tient en une seule ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print re.findall('#\d+', description)
    ou certainement plus efficace dans un vrai programme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pat = re.compile('#\d+')
    print re.findall(pat, description)
    Si vous ne voulez pas les '#' dans les chaines:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print re.findall('(?<=#)\d+', description)
    Si vous voulez autoriser les '+' et les '-':
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print re.findall('(?<=#)[-+]?\d+', description)
    Si vous ne voulez pas utiliser les regex, vous pouvez dégrossir avec un split('#') (le '-' sert à être sûr que la première occurrence ne commencez pas par '#'):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for chunk in  ('-' + description).split('#')[1:]:
      print chunk.split()[0].split('.')[0].split(')')[0]
    La dernière ligne est un peu improvisée. En fait, ça vient du fait que comme souvent avec ce genre de question le problème n'est qu'imparfaitement défini. Peut-il y avoir un espace entre '#' et le premier chiffre ? Peut-il y avoir un nombre "à virgule" ? etc.
    En fait, si vous définissez le problème par l'exemple, je réponds:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print '#124\n#125\n#126\n#98'

    Bonne journée...

  8. #8
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Merci beaucoup Pierre pour cette réponse très efficace !
    Notamment celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print re.findall('(?<=#)\d+', description)
    Je me permet de vous demander si je veux ajouter une condition à partir de cette expression, que je n'affiche que les #nombre seulement s'il n'y a pas la chaine "source:" dans le mot. (J'appelle mot l'ensemble de caractère qui contient le #nombre avec tous les caractères adjacents, s'arretant aux espaces. En fait plus généralement je veux récupérer tous les #nombre qui ne sont pas des ancres d'une url...
    Exemple de ce que je veux conserver :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    source:/#33      -> non
    source:/link#33   -> non
    source:/link#33abc -> non
    (source:/link#33) -> non
    source:/link #33   -> oui
    (source:/link #33) -> oui
    (#33)               -> oui
    [#33]               -> oui
    lala #33.         -> oui
    toto:#33)        -> oui
    J'ai vu qu'on peut utiliser (?!...) pour interdire une certaine expression mais je ne sais pas trop comment l'utiliser... J'ai essayé ca qui ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print re.findall('(?!source:)(?<=#)\d+', description)
    Je risque d'avoir beaucoup de cas à tester... Sauriez-vous comment réaliser ceci simplement ?

  9. #9
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Je remet ce que j'ai fait, j'essaye de ne pas prendre les 2 nombres (#125 et #1) qui sont après "source".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    import re
     
    description = " Ticket Id=120, Owner=tgor3401,#20 #20 #20#20 ng short of a r=tgor3401, time=26:19:52 code. #124 source#125 #126.Ticket 120 author=tgor3401, time=2006-09-15 15:19:21, , newvalue=closed. (#98) Ticket 120 author=tgor3401t..Ticket #20, organise images into one ticket:1111 folder [source:/#1 SVN Revision 1] "
     
    listTicketsQuoted = []
    pat = re.compile('(?<!source)re.S*(?<=#)\d+')
    listTicketsQuoted.extend(re.findall(pat, description))
    print listTicketsQuoted
    J'ai essayé ceci mais ca ne marche pas, je voulais dire que ma chaine ne contienne pas "source", puis contienne 0 ou plusieurs caractères (non espace) quelconques, puis un #, puis le numéro. Mais je ne récupère rien... (liste vide).

    Alors j'ai aussi essayé ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    import re
     
    description = " Tic Id=120, Owner=tgor3401,#20 #20 #20#20  a r=tgor3401, time=26:19:52 code. #124 dddsource#125 #126.Ticket 120 author=tgor3401, time=2006-09-15 15:19:21, , newvalue=closed. (#98) Ticket 120 author=tgor3401t..Ticket #20, organise images into one ticket:1111 folder [source:/#1 SVN Revision 1] "
     
    listTicketsQuoted = []
    pat = re.compile('(?<!source)#\d+')
    listTicketsQuoted.extend(re.findall(pat, description))
    print listTicketsQuoted
    Et j'ai ca qui s'affiche : ['#20', '#20', '#20', '#20', '#124', '#126', '#98', '#20', '#1'] donc c'est pas trop mal, mais le problème c'est que j'ai le dernier #1 que je ne veux pas car
    "[source:/#1" contient "source" mais ca a l'air de bugguer avec les caractères spéciaux... et si j'ai des caractères entre "source" et "#125" ca prend le nombre 125 dans la liste, ce que je ne veux pas!
    (bon j'ai aussi les dièses qui apparaissent maintenant mais c'est moins grave)

  10. #10
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Bonjour,

    Je ne suis pas bon en regex. Comme vous avez l'air coincé, je vous propose un truc bidouillé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    results = [elem[1:] for elem in re.findall('source\S*\d+|#\d+', description) if elem[0] == '#']
    Un code plus long qui se veut auto-explicatif:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    pat1 = re.compile('#\d+')
    pat2 = re.compile('source\S*\d+')
    patf = re.compile('source\S*\d+|#\d+')
    print re.findall(pat1, description)
    print re.findall(pat2, description)
    print re.findall(patf, description)
    results = [elem[1:] for elem in re.findall(patf, description) if elem[0] == '#']
    print results
    - Dans 'A|B', quand on a trouvé quelque chose par A, on ne cherche plus "dedans" par B. Ce qui signifie que vous trouverez le 'source#125' (par A) vous ne trouverez pas ensuite le '#125' par B.
    - Un autre truc: dans les formes type (?<=...) (un back-kkchose, recherche en arrière), '...' doit avoir une longueur fixe, ce qui élimine certaines idées de solutions.

    Il y a certainement plus élégant, sur la même base mais en étudiant la notion de groupe. Mais il n'est pas dit que ce sera plus performant, je n'en sais rien.

    Bon courage,
    Pierre

  11. #11
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Avec les groupes "non capturing", on peut faire un peu moins crade:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pattest = re.compile('(?:source\S*\d+)|((?<=#)\d+)')
    results = re.findall(pattest, description)
    print results
    print [x for x in results if len(x)]
    Doit y avoir mieux...

  12. #12
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Merci énormément !
    Dernière petite précision. Si je veux aussi prendre le numéro 1111 qui est reconnu car juste derrière "ticket:". Je l'ai fait en 2 recherches comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import re
     
    description = " Tic Id=120, Owner=tgor3401,#20 #20 #20#20  a r=tgor3401, time=26:19:52 code. #124 dddsource#125 #126.Ticket 120 author=tgor3401, time=2006-09-15 15:19:21, , newvalue=closed. (#98) Ticket 120 author=tgor3401t..Ticket #20, organise images into one ticket:1111 folder [source:/#1 SVN Revision 1] "
     
    resultsPat = []
    results = []
    pattest = re.compile('(?:source\S*\d+)|((?<=#)\d+)')
    results = re.findall(pattest, description)
    pattest = re.compile('(?<=ticket:)\d+')
    results.extend(re.findall(pattest, description))
    for x in results:
      if len(x): resultsPat.append(x)
    print resultsPat
    J'ai essayé de mettre un autre 'OR' comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pattest = re.compile('(?<=ticket:)\d+|(?:source\S*\d+)|((?<=#)\d+)')
    mais ça ne prend pas le 1111. Enfin, de toute façon déjà votre solution marche et je vous en remercie encore sincèrement.

  13. #13
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pattest = re.compile('(?:source\S*#\d+)|((?<=#)\d+|(?<=ticket:)\d+)')

  14. #14
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Re,

    Je répète que je ne suis pas aguerri aux regex, ni même au Python subtil, et ce n'est pas de la coquetterie. En fait, c'est comme "Belle du Seigneur", d'Albert Cohen (ou "Ulysse", de James Joyce), j'ai une culpabilité de ne pas être dans le coup, et de temps en temps je redémarre à zéro
    Merci donc de m'y avoir aidé par vos questions.
    Vous me faites un peu peur. Vous rajoutez des critères peu à peu, pas nécessairement cohérents. Déjà, il serait compliqué d'ajouter une chaîne précédent le nombre qui n'aurait pas une longueur fixe, accepter par exemple 111 avec 'ticket: 111'.
    Si vous n'êtes pas en mesure d'analyser à l'avance vos contraintes, il serait préférable de remettre tout à plat en allant vers plus de souplesse. Je vous propose une base:
    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
    35
    36
    37
    #! /usr/bin/env python
    # -*- coding: iso-8859-1 -*-
     
     
    import re
     
    def dopatternstring(liste, pattern):
      patterns = pattern.split('PATS')
      searchstring = patterns[0] + liste[0]
      for s in liste[1:]:
        searchstring += '|' + s
      return searchstring + patterns[1]
     
    description = \
    "tgor3401,#20 trouduc#20 #20#20  a r=tgor3401, \
    ti #124 dddsource#125 petrus#126.Ticket: 120 author=tgor3401, \
    time=2006-09-15 15:19:21, , newvalue=closed. (#98) Ticket 120 \
    author=tgor3401t..Ticket #20, organise images into one \
    ticket: 1111 folder [source:/#1 SVN Revision 1] "
     
     
    REJECTPATTERN = '(?:PATS\d+)'
    REJECTS = [
               'source\S*#'
             , 'petrus#'
              ]
     
    ACCEPTPATTERN = '(?:PATS)(\d+)'
    ACCEPTS = [
               '#'
             , 'ticket:'
              ]
     
    searchstring = dopatternstring(REJECTS, REJECTPATTERN)\
                 + '|'\
                 + dopatternstring(ACCEPTS, ACCEPTPATTERN)
    print [x for x in re.compile(searchstring).findall(description) if len(x)]
    Vous ajoutez dans les listes REJECTS et ACCEPTS les regex élémentaires que vous voulez.
    Par exemple (j'ai modifié votre chaîne) en modifiant 'ticket:' en 'ticket:\s*', vous récupérez le 1111. Avec '[Tt]icket:\s*', vous récupérez un 120. Avec '[Tt]ickets?\s*:\s*', des tickets au singulier ou au pluriel, avec majuscule initiale ou non, et avec un ':' à la fin, mais éventuellement précédé et/ou suivi d'espace.
    Pour les performances, je n'ai rien testé, mais voyez bien que la majorité du code ne se déroule qu'une fois.
    Voilà, pas de commentaires dans le code, pas d'explications, n'hésitez pas à demander.

    Bonne journée,

    Pierre

  15. #15
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Oui désolé de vous faire peur, je suis confus.
    La c'était vraiment ma dernière condition donc ne vous inquiétez pas !
    Je ne veux pas prendre les espaces après 'ticket' et pas de majuscule sur le 'T' ou de 's' pluriel.

    Avec votre dernier code et en modifiant juste la liste REJECTS comme ceci c'est totalement parfait ! Je n'aurais pas pu espérer mieux.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    REJECTS = [
               'source\S*#'
             , 'http\S*#'
             , 'www\S*#'
             , '!#'
              ]
    Donc voilà je vous remercie encore pour votre précieuse aide !

  16. #16
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Bonjour, j'ai à nouveau une question sur les expressions régulières.
    Dans cette chaine "(15, S, 25), (7, c, 4), (15, S, 25), (9, d, 3), (8, b, 4) " je recherche tout ce qui est proche du pattern (13, S, 22), (8, b, 4).
    (15, S, 25), (7, c, 4) et (15, S, 25), (8, b, 4) sont 2 solutions possibles, mais même en utilisant la fonction re.findall python ne m'en retourne qu'une seule !

    Pour moi un pattern est un ensemble (chiffre|lettre, chiffre|lettre, chiffre|lettre).

    Quelqu'un pourrait-il m'aider à réaliser ceci ? Voici mon code avec les sorties que j'ai et que j'attends.


    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    #!/usr/bin/python
    # -*- coding: utf-8 -*- 
     
    import re
     
    digits = '0123456789'
    #letters = 'abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
     
    description = "(15, S, 25), (7, c, 4), (15, S, 25), (9, d, 3), (8, b, 4) "
    patterns = ["13, S, 22", "8, b, 4"]
    print "description=", description
    print "patterns=", patterns
     
    regexStringTemp = ""
    regexString = ""
     
    def generateRegexStringInt(val):
      regexStringPart =""
      if val <10: 
        threshold=1
      else:
        threshold = int(repr(val)[:-1]) +1 # delete unity: 16-> 1+1, 57-> 5+1, 234-> 23+1
      for i in range(val-threshold, val+threshold+1):
        regexStringPart = regexStringPart + str(i)  +"|"
      return regexStringPart[:-1]
     
    def generateRegexStringLetter(val):
      if val in 'TLSVN':
        return val
      else:
        return chr(ord(val)-1) +"|"+ val +"|"+ chr(ord(val)+1)
     
    for pattern in patterns:
      values = pattern.split(", ")
      if values[0][0] in digits:
        part1 = generateRegexStringInt(int(values[0]))
      else:
        part1 = generateRegexStringLetter(values[0])
      if values[1][0] in digits: 
        part2 = generateRegexStringInt(int(values[1]))
      else:
        part2 = generateRegexStringLetter(values[1])
      if values[2][0] in digits:
        part3 = generateRegexStringInt(int(values[2]))
      else:
        part3 = generateRegexStringLetter(values[2])
     
      regexStringPart1 = "\((" + part1 
      regexStringPart1 = regexStringPart1 + "), ("
     
      regexStringPart3 = "), (" + part3
      regexStringPart3 = regexStringPart3 +")\)"
     
      #regexStringPart2 = "), ("+ str(val2 -1) +"|"+ str(val2) +"|"+ str(val2 +1) +")\)"
     
      regexString = regexString + regexStringPart1 + part2 + regexStringPart3 + ".*" 
     
    regexString = regexString[:-2]  #remove the last  ','
    print "regexString="+regexString 
     
    listNear= []
    regexPat = re.compile(regexString)			#regexPat = re.compile("\(15, S, 25\),(?<=.*)\(15, b, 2\)")	
    listNear.extend(re.findall(regexPat, description))		#regexPat = re.compile(regexString)
    print "listNear"+str(listNear)
     
    for near in listNear:
      lapin = "("+ str(list(near))[1:-1] +") "
      print "lapin"+lapin  
     
    # lapin('15', 'S', '25', '8', 'b', '4')
    # je voudrais les 2 solutions possibles:  (15, S, 25), (7, c, 4) et (15, S, 25),  (8, b, 4) ce dernier étant séparé par (9, d, 3) que je n'ai pas besoin de conserver.
     
    teststr = []
    for near in listNear:
      tmp = "".join("[")
      for n in range(0, len(near), 3):
        tmp = tmp + "("+ near[n] +", "+ near[n+1] +", "+ near[n+2] +")"
      tmp = tmp +  "]"
      teststr.append(tmp)
    print "teststr=",teststr
     
    # teststr= ['[(15, S, 25)(8, b, 4)]']
    # Je voudrais de même ici trouvé les 2 solutions possibles.
    Si je remplace cette ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      regexString = regexString + regexStringPart1 + part2 + regexStringPart3 + ".*"
    par celle-ci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    regexString = regexString + regexStringPart1 + part2 + regexStringPart3 + ", "
    Celà fonctionne mais je n'obtiens que des patterns qui sont collés les uns aux autres, et je veux pouvoir en trouver comme celui ci (15, S, 25), (9, d, 3), (8, b, 4) avec des autres patterns présents au milieu (comme dans ce cas trouver (15, S, 25), (8, b, 4) avec (9, d, 3) au milieu).

    Merci

  17. #17
    Candidat au Club
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Points : 2
    Points
    2
    Par défaut
    Bonjour et Joyeux Noel a tous ! (desole pour les accents je suis sur un clavier qwerty).

    Est-ce que quelqu'un pourrait m'aider pour le probleme que j'ai cite ci-dessus ?

Discussions similaires

  1. [VB]Travailler sur un string
    Par Little-Freud dans le forum VB 6 et antérieur
    Réponses: 17
    Dernier message: 21/05/2006, 17h05
  2. Débutant travailler sur des images
    Par doud dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 15/08/2005, 16h47
  3. [débutant]travailler sur contenu string
    Par Serge76 dans le forum SL & STL
    Réponses: 13
    Dernier message: 06/11/2004, 17h43
  4. Travailler sur des sources distantes avec Eclipse
    Par El Saigneur dans le forum Eclipse Java
    Réponses: 5
    Dernier message: 12/07/2004, 10h40
  5. Travailler sur des données qui doivent être triées
    Par haypo dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 19/07/2003, 18h13

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