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 :

Utiliser les REGEX


Sujet :

Python

  1. #1
    Membre habitué
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Par défaut Utiliser les REGEX
    Bonjour,

    Je travaille avec les expressions régulières.
    J'ai fait ceci qui marche, la sortie attendue est la bonne, mais j'utilise 2 expressions régulières et 2 boucles.
    Quelqu'un saurait-il comment améliorer celà, peut-être en une seule expression régulière ? (pour récupérer les chiffres 1 2 3 4 5 6 7 8 9 à la fin de ma description)
    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
     
    import re
     
    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=tgor301t..Ticket #20, organise images into one !#678 \
    ticket: 1111 ticket:111 folder [se:/#1 SVN Rn 1] abla#1234 ticket `#12`:trac:<>[4:2] -- \
    Opens change set 42 </li><li>#42 -- Opens ticket number 42 </li><li>{1} -- Opens report 1 \
    Changesets: r1, [2], changeset:3 or (restricted) [4/trunk], changeset:5/trunk, [6:9/trunk] changeset:berk"
     
    searchstring = "changeset:\d+|\[\d+\]|\[\d+/\S+]|\[\d+:\d+/\S+]|\Wr\d+"
    resultsPat = []
    for x in re.compile(searchstring).findall(description):			
      if len(x): 							# for each changeset found
        ltempo = []
        for num in re.compile("\d+").findall(x):			# take the number of revision
          ltempo.append(int(num))
        if len(ltempo) == 2 and int(ltempo[0]) < int(ltempo[1]) :   # if there are 2 numbers, there is an interval
          ltempo = range(int(ltempo[0]), int(ltempo[1])+1) 		# take all the revisions between first and last 
        print ltempo
        resultsPat.extend(ltempo)
    print resultsPat
    #[1]
    #[2]
    #[3]
    #[4]
    #[5]
    #[6, 7, 8, 9]
    #[1, 2, 3, 4, 5, 6, 7, 8, 9]

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

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

    Je ne vois pas trop comment régler ça en un seul regex, mais je ne suis pas vraiment entré dans votre programme. J'ajoute que je suis obsédé du Un programme ne doit pas faire plus d'une ligne, mais que je le regrette de plus en plus souvent quand je reprends mon code, quand je n'y comprends plus rien. En gros, quand un joli truc vous demande une demi-heure de travail, il vous en faudra autant pour le piger un mois plus tard
    - La première chose qui me frappe c'est d'appeler re.compile("\d+") dans la boucle extérieure. J'imagine que l'interprêteur optimise ça (et encore, je n'en sais rien), mais je trouve ce genre de truc crade, quel que soit le langage d'ailleurs.
    - Vous pouvez remplacer une boucle par une "list comprehension".
    - Je ne suis pas sûr que le if len(x): soit utile.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    resultsPat = []
    reobj1 = re.compile("changeset:\d+|\[\d+\]|\[\d+/\S+]|\[\d+:\d+/\S+]|\Wr\d+")
    reobj2 = re.compile("\d+")
    for x in reobj1.findall(description):
      ltempo = [int(num) for num in reobj2.findall(x)]
      if len(ltempo) == 2 and int(ltempo[0]) < int(ltempo[1]):
        ltempo = range(int(ltempo[0]), int(ltempo[1])+1)
      print ltempo
      resultsPat.extend(ltempo)
    print resultsPat

  3. #3
    Membre habitué
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Par défaut
    Très bien merci de votre aide, pertinente comme toujours !

    J'ai à nouveau une question sur les expressions régulières. J'en avais déjà parlé dans un autre message (si un modérateur peut effacer l'autre message dans "Travail sur des Strings" ca pourrait éviter un double post).
    Ceci est vraiment important pour la suite (et fin) de mon travail.

    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).

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

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Par défaut
    Citation Envoyé par Pingvince Voir le message
    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).
    Là, je penserais qu'un 'pattern', c'est un truc de la forme (chiffre, lettre, chiffre),(chiffre, lettre, chiffre). Mais je me demande ce que peut bien signifier "est proche de".
    Pour moi un pattern est un ensemble (chiffre|lettre, chiffre|lettre, chiffre|lettre).
    J'avais faux sur la pattern.
    Votre code n'aide pas à comprendre ce que vous voulez faire. Prenez le temps d'expliquer, ça nous éclairera et peut-être que ça vous aidera à vous aussi.
    Je ne suis pas certain que votre apprche tout regex soit la bonne. Peut-être définir un objet (classe ?) de forme (chiffre|lettre, chiffre|lettre, chiffre|lettre), écrire des fonctions (méthodes ?) estProche(), estDeLaForme(string), etc. ?

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    119
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 119
    Par défaut
    Bonjour,

    en ce qui concerne le premier post, est ce que vous avez essayé les groupes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    changeset:(\d+)|\[(\d+)\]|\[(\d+)/\S+]|\[(\d+):(\d)+/\S+]|\Wr(\d+)
    en utilisant les groupes nommés, on peut directement retirer les nombres.

    Pour le deuxième, je n'ai toujours pas bien compris ce que vous cherchiez. Je suppose que vous cherchez des patterns "\((\d+),(\w+),(\d+)\)" et vous voulez les comparer à un ensemble de patterns pour savoir s'ils sont "proches". Si c'est le cas, je fabriquerais une class "Pattern" capable de se construire à partir d'une string (avec la regex ci-dessus), et dotée d'une fonction distance(self,other) et une autre distanceset(self,setofpattern). Le filtrage devrait ensuite être simple.

    Sinon, il faudrait mieux décrire le besoin...

  6. #6
    Membre habitué
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Par défaut
    Bonjour et merci de vos réponses.
    Merci Fructidor pour votre message sur mon 1er post, en effet ca fonctionne très bien.

    Pour la 2ème question Pierre, un pattern est dans cet example (chiffre, lettre, chiffre), (chiffre, lettre, chiffre). Mais ce n'est qu'un example.
    Un pattern peut-être en 1 ou plusieurs parties constituées comme ceci:
    (chiffre OU lettre, chiffre OU lettre, chiffre OU lettre)
    Donc dans cette example j'ai pris un pattern de 2 parties de la forme (chiffre, lettre, chiffre).

    Quand je dis "est proche de" cela correspond à mes 2 fonctions generateRegexStringInt() et generateRegexStringLetter(). Example avec le pattern "(13, S, 22), (8, b, 4)". Les patterns qui sont proches sont ceux qui matchent avec regexString, dans cet example regexString = "\((11|12|13|14|15), (S), (19|20|21|22|23|24|25)\).*\((7|8|9), (a|b|c), (3|4|5)\)"
    Soit:
    "(11, S, 22), (8, b, 4)"
    "(12, S, 22), (8, b, 4)"
    "(13, S, 22), (8, b, 4)"
    "(14, S, 22), (8, b, 4)"
    "(15, S, 22), (8, b, 4)"

    "(11, S, 19), (8, b, 4)"
    ...

    Je ne cherche pas à avoir la distance entre les parties mais simplement à savoir combien de fois le pattern a été trouvé dans cette chaine (même si les parties du pattern sont séparées dans la chaine). Si je peux récupérer quelles valeurs ont été utilisées pour matcher avec le pattern rechercher c'est mieux.

    Peut-être que maintenant cet example que j'avais donné, et qui est censé résumer tout ça, est plus compréhensible:
    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, et que je veux trouver

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

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Par défaut
    Citation Envoyé par Pingvince Voir le message
    Peut-être que maintenant cet example que j'avais donné, et qui est censé résumer tout ça, est plus compréhensible:
    Malheureusement, non. Un exemple n'est pas un cahier des charges. Par exemple, que souhaitez-vous obtenir avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    description = "(15, S, 24), (7, z, 4), (15, S, 25), (9, d, 3), (8, b, 4) "
    ?
    Est-ce (15, S, 24) , (8, b, 4) et (15, S, 25) , (8, b, 4) ? Est-ce (15, S, 24) , (8, b, 4) seulement ? Ou alors (15, S, 25) , (8, b, 4) seulement ?

    De plus j'ai l'impression que votre usine à regex n'est pas très stable. Un simple espace en plus ou en moins dans description et ça ne marche plus. Je vous propose, à terminer en fonction de votre cahier des charges, un truc plus maintenable:
    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*- 
     
    import re
     
    def estProche(patbase, pat):
      return pat[0] in patbase[0] and ord(pat[1]) in patbase[1] and pat[2] in patbase[2]
     
    def cherchePremier(liste, debut, patbase):
      for i in range(debut + 1, len(liste)):
        if estProche(patbase, liste[i]):
          return i
      return None
     
    def normaliseTriplet(triplet):
      if len(triplet) != 3:
        return None
      return [int(triplet[0]), triplet[1].strip(), int(triplet[2])]
     
    def rangefy(triplet, delta):
      bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[1].isupper()]
      return [
              range(max(triplet[0] - delta[0], 0), triplet[0] + delta[0] + 1)
            , range(max(ord(triplet[1]) - delta[1], bornes[0]), min(ord(triplet[1]) + delta[1] + 1, bornes[1])) 
            , range(max(triplet[2] - delta[2], 0), triplet[2] + delta[2] + 1)
              ] 
     
    def normalisePatterns(patterns):
      if len(patterns) != 2:
        return None
      pat = [normaliseTriplet(x.split(',')) for x in patterns]
      return rangefy(pat[0], prox1), rangefy(pat[1], prox2)
     
     
     
    description = "(15, S, 25), (7, c, 4), (15, S, 25), (9, d, 3), (8, b, 4) "
    patterns = ["13, S, 22", "8, b, 4"]
    prox1 = [2, 0, 3]
    prox2 = [1, 1, 1]
    tripletsStrings = re.findall("\([a-zA-Z0-9 ,]*\)", description)
    desc = [normaliseTriplet(x[1:-1].split(',')) for x in tripletsStrings]
    P1, P2 = normalisePatterns(patterns)
     
     
    for i in [i for i in range(0, len(desc)) if estProche(P1, desc[i])]:
      y = cherchePremier(desc, i, P2)
      if y:
        print tripletsStrings[i], ',', tripletsStrings[y], ' -- (', i, ',', y, ')'

  8. #8
    Membre habitué
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Par défaut
    Bonjour Pierre,
    C'est exactement ce qu'il me faut dans le cas de 2 patterns !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    description = "(15, S, 24), (7, z, 4), (15, S, 25), (9, d, 3), (8, b, 4) "
    Pour celà je veux en effet (15, S, 24) , (8, b, 4) et (15, S, 25) , (8, b, 4).

    Description est une chaîne que je génère automatiquement, elle est toujours strictement sous cette forme. Il ne peut pas y avoir d'espaces en plus par exemple.

    Modifications à apporter:
    Est-il possible de généraliser une telle méthode, pour que ces fonctions soient valables quelque soit le même nombre de partie dans le pattern ? Ici celà marche très bien pour 2 parties, mais pas avec 1 partie, ni 3, ni 4, etc...

    Il faudrait que les patterns soient trouvés aussi pour des patterns de forme (lettre, chiffre, lettre) ou (chiffre, lettre, lettre) etc...

    Voici comme je l'ai modifié ce n'est pas encore parfait, mais ca s'en approche.

    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
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
     
    import re
     
    digits = '0123456789'
     
    # Test si on trouve une partie pat "proche" de la partie du pattern patbase
    def estProche(patbase, pat):
     
      if isIntElem1: elem1 = pat[0] in patbase[0]
      else:          elem1 = ord(pat[0]) in patbase[0]
     
      if isIntElem2: elem2 = pat[1] in patbase[1]
      else:          elem2 = ord(pat[1]) in patbase[1]
     
      if isIntElem3: elem3 = pat[2] in patbase[2]
      else:          elem3 = ord(pat[2]) in patbase[2]
     
      return elem1 and elem2 and elem3
     
     
    # Retourne l'indice du pattern trouver
    def cherchePremier(liste, debut, patbase):
      for i in range(debut + 1, len(liste)):
        if estProche(patbase, liste[i]):
          return i
      return None
     
    def normaliseTriplet(triplet):
      if len(triplet) != 3:
        return None
     
      if isIntElem1: elem1 = int(triplet[0])
      else:          elem1 = triplet[0].strip()
     
      if isIntElem2: elem2 = int(triplet[1])
      else:          elem2 = triplet[1].strip()
     
      if isIntElem3: elem3 = int(triplet[2])
      else:          elem3 = triplet[2].strip()
     
      return [elem1, elem2, elem3]
     
     
    def rangefy(triplet, delta):
     
      if isIntElem1: elem1 = range(max(triplet[0] - delta[0], 0), triplet[0] + delta[0] + 1)
      else: 
        bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[0].isupper()]
        elem1 = range(max(ord(triplet[0]) - delta[0], bornes[0]), min(ord(triplet[0]) + delta[0] + 1, bornes[1])) 
     
      if isIntElem2: elem2 = range(max(triplet[1] - delta[1], 0), triplet[1] + delta[1] + 1)
      else:       
        bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[1].isupper()]
        elem2 = range(max(ord(triplet[1]) - delta[1], bornes[0]), min(ord(triplet[1]) + delta[1] + 1, bornes[1])) 
     
      if isIntElem3:
        elem3 = range(max(triplet[2] - delta[2], 0), triplet[2] + delta[2] + 1)
      else: 
        bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[2].isupper()]
        elem3 = range(max(ord(triplet[2]) - delta[2], bornes[0]), min(ord(triplet[2]) + delta[2] + 1, bornes[1])) 
     
      return [elem1, elem2, elem3]
     
     
    def normalisePatterns(patterns, prox1, prox2):
     
      pat = [normaliseTriplet(x.split(', ')) for x in patterns]
      P1 = rangefy(pat[0], prox1)
      listP2 = [rangefy(pat[i], prox2) for i in range(1, len(patterns))]
      return P1, listP2 
     
     
     
    description = "(a, S, 25), (e, c, 4), (b, S, 24), (z, d, 3), (c, d, 4), (a, S, 26) "
    patterns = ["a, S, 22", "d, d, 4", "a, S, 25"]
     
     
    tripletsStrings = re.findall("\([a-zA-Z0-9 ,]*\)", description)
    print "tripletsStrings=" + str(tripletsStrings)
     
    listTriplets = [x[1:-1].split(', ') for x in tripletsStrings]
    print "listTriplets="+ str(listTriplets) 
     
    # Test the shape of the pattern (int|letter, int|letter, int|letter)
    if listTriplets[0][0][0] in digits: isIntElem1 = True
    else:                               isIntElem1 = False  
    if listTriplets[0][1][0] in digits: isIntElem2 = True
    else:                               isIntElem2 = False
    if listTriplets[0][2][0] in digits: isIntElem3 = True
    else:                               isIntElem3 = False  
    print str(isIntElem1)+ str(isIntElem2)+ str(isIntElem3)
     
    desc = [normaliseTriplet(x[1:-1].split(', ')) for x in tripletsStrings]
    print "desc="+ str(desc) 
     
    prox1 = [2, 0, 3]
    prox2 = [1, 1, 1]
    P1, listP2 = normalisePatterns(patterns, prox1, prox2)
    print "P1="+str(P1)
    print "listP2="+str(listP2)
     
     
    listAllPattFound = []
    for i in [i for i in range(0, len(desc)) if estProche(P1, desc[i])]:	# si on a trouvé la 1ere partie du pattern
      listPattFound = []
      listy = []
      indicePrecedent = i
      print "indicePrecedent="+str(indicePrecedent)
      print "tripletsStrings[i]="+tripletsStrings[i]
      listPattFound.append(tripletsStrings[i])
     
      for j in listP2: 					# pour chaque partie du pattern
        indiceCourant=cherchePremier(desc, indicePrecedent, j)
        listy.append(indiceCourant)
        indicePrecedent = indiceCourant
      print 'listy='+str(listy)
     
      if None not in listy :
        for y in listy:
          print "tripletsStrings[y]="+tripletsStrings[y]
          listPattFound.append(tripletsStrings[y])
        listAllPattFound.append(listPattFound)
     
    for pattFound in listAllPattFound:
      print pattFound
    J'ai en sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ['(a, S, 25)', '(e, c, 4)', '(b, S, 24)']
    ['(b, S, 24)', '(c, d, 4)', '(a, S, 26)']
    Alors que je ne devrais avoir que ['(a, S, 25)', '(e, c, 4)', '(b, S, 24)'] car le 2ème pattern trouvé reprend une partie du 1er. le (b, S, 24) n'apparait qu'une fois dans la chaine donc ne devrait pas être pris en compte pour trouver un second pattern.

    Même avec votre code, ce problème apparait si l'on utilise ces données:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    description = "(1, T, 1), (1, T, 1), (1, T, 1) "
    patterns = ["1, T, 1", "1, T, 1"]
    La sortie est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (1, T, 1) , (1, T, 1)  -- ( 0 , 1 )
    (1, T, 1) , (1, T, 1)  -- ( 1 , 2 )
    au lieu de seulement (1, T, 1) , (1, T, 1) -- ( 0 , 1 ) comme je le voudrais.

  9. #9
    Membre habitué
    Inscrit en
    Octobre 2007
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 15
    Par défaut
    Ca yest je suis arrivé à quelque chose qui me va pour des patterns de au minimum 2 parties. Voici le code (peut être peut-on l'améliorer).

    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
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
     
    # Test si on trouve une partie pat "proche" de la partie du pattern patbase
    def estProche(patbase, pat):
     
      if isIntElem1: elem1 = pat[0] in patbase[0]
      else:          elem1 = ord(pat[0]) in patbase[0]
     
      if isIntElem2: elem2 = pat[1] in patbase[1]
      else:          elem2 = ord(pat[1]) in patbase[1]
     
      if isIntElem3: elem3 = pat[2] in patbase[2]
      else:          elem3 = ord(pat[2]) in patbase[2]
     
      return elem1 and elem2 and elem3
     
     
    # Retourne l'indice du pattern trouver
    def cherchePremier(liste, debut, patbase):
      for i in range(debut + 1, len(liste)):
        if estProche(patbase, liste[i]):
          return i
      return None
     
    def normaliseTriplet(triplet):
      if len(triplet) != 3:
        return None
     
      if isIntElem1: elem1 = int(triplet[0])
      else:          elem1 = triplet[0].strip()
     
      if isIntElem2: elem2 = int(triplet[1])
      else:          elem2 = triplet[1].strip()
     
      if isIntElem3: elem3 = int(triplet[2])
      else:          elem3 = triplet[2].strip()
     
      return [elem1, elem2, elem3]
     
     
    def rangefy(triplet, delta):
     
      if isIntElem1: elem1 = range(max(triplet[0] - delta[0], 0), triplet[0] + delta[0] + 1)
      else: 
        bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[0].isupper()]
        elem1 = range(max(ord(triplet[0]) - delta[0], bornes[0]), min(ord(triplet[0]) + delta[0] + 1, bornes[1])) 
     
      if isIntElem2: elem2 = range(max(triplet[1] - delta[1], 0), triplet[1] + delta[1] + 1)
      else:       
        bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[1].isupper()]
        elem2 = range(max(ord(triplet[1]) - delta[1], bornes[0]), min(ord(triplet[1]) + delta[1] + 1, bornes[1])) 
     
      if isIntElem3:
        elem3 = range(max(triplet[2] - delta[2], 0), triplet[2] + delta[2] + 1)
      else: 
        bornes = ([ord('a'), ord('z') + 1], [ord('A'), ord('Z') + 1])[triplet[2].isupper()]
        elem3 = range(max(ord(triplet[2]) - delta[2], bornes[0]), min(ord(triplet[2]) + delta[2] + 1, bornes[1])) 
     
      return [elem1, elem2, elem3]
     
     
    def normalisePatterns(patterns, prox1, prox2):
     
      pat = [normaliseTriplet(x.split(', ')) for x in patterns]
      P1 = rangefy(pat[0], prox1)
      listP2 = [rangefy(pat[i], prox2) for i in range(1, len(patterns))]
      return P1, listP2 
     
     
     
    description = "(a, S, 25), (e, c, 4), (z, z, 3), (b, S, 24), (z, d, 3), (c, d, 4), (a, S, 26) "
    patterns = ["a, S, 22", "d, d, 4", "a, S, 25"]
    description = "(1, T, 1), (1, T, 1), (1, T, 1), (1, T, 1) "
    patterns = ["1, T, 1", "1, T, 1"]
     
    tripletsStrings = re.findall("\([a-zA-Z0-9 ,]*\)", description)
    #print "tripletsStrings=" + str(tripletsStrings)
     
    listTriplets = [x[1:-1].split(', ') for x in tripletsStrings]
    #print "listTriplets="+ str(listTriplets) 
     
    # Test the shape of the pattern (int|letter, int|letter, int|letter)
    if listTriplets[0][0][0] in digits: isIntElem1 = True
    else:                               isIntElem1 = False  
    if listTriplets[0][1][0] in digits: isIntElem2 = True
    else:                               isIntElem2 = False
    if listTriplets[0][2][0] in digits: isIntElem3 = True
    else:                               isIntElem3 = False  
    print str(isIntElem1)+ str(isIntElem2)+ str(isIntElem3)
     
    desc = [normaliseTriplet(x[1:-1].split(', ')) for x in tripletsStrings]
    print "desc="+ str(desc) 
     
    prox1 = [2, 0, 3]
    prox2 = [1, 1, 1]
    P1, listP2 = normalisePatterns(patterns, prox1, prox2)
    #print "P1="+str(P1)
    #print "listP2="+str(listP2)
     
     
    listAllPattFound = []
    for i in [i for i in range(0, len(desc)) if estProche(P1, desc[i])]:	# si on a trouvé la 1ere partie du pattern
      listPattFound = []
      listy = []
      indicePrecedent = i
    #  print "indicePrecedent="+str(indicePrecedent)
    #  print "tripletsStrings[i]="+tripletsStrings[i]
      listPattFound.append([tripletsStrings[i], i])
     
      for j in listP2: 					# pour chaque partie du pattern
        indiceCourant=cherchePremier(desc, indicePrecedent, j)
        listy.append(indiceCourant)
        indicePrecedent = indiceCourant
    #  print 'listy='+str(listy)
     
     
      if None not in listy :
        for y in listy:
          #print "tripletsStrings[y]="+tripletsStrings[y]
          listPattFound.append([tripletsStrings[y], y])
        listAllPattFound.append(listPattFound)
     
    print listAllPattFound
     
    # Pour éliminer ce cas où 2 patterns étaient trouvées au lieu d'un seul: 
    # description = "(1, T, 1), (1, T, 1), (1, T, 1) "
    # patterns = ["1, T, 1", "1, T, 1"]
    # 
    pattPrec = listAllPattFound[0]
    listAllPattFoundFinal = []
    for pattFound in listAllPattFound:
      # si la derniere partie du pattern précédent est au même indice que la première partie du pattern courant 
      if pattPrec[-1][1] !=  pattFound[0][1]:
        listAllPattFoundFinal.append(pattFound)
     
     
    for pattFound in listAllPattFoundFinal:  
      string = ""
      for patt in pattFound:
        string = string + patt[0]
      string = string + ' -- (' 
      for patt in pattFound:
        string = string + str(patt[1]) + ', '
      string = string[:-2] + ') --' 
      print string
    Entrée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    description = "(1, T, 1), (1, T, 1), (1, T, 1), (1, T, 1) "
    patterns = ["1, T, 1", "1, T, 1"]
    Sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    (1, T, 1)(1, T, 1) -- (0, 1) --
    (1, T, 1)(1, T, 1) -- (2, 3) --
    Entrée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    description = "(a, S, 25), (e, c, 4), (z, z, 3), (b, S, 24), (z, d, 3), (c, d, 4), (a, S, 26) "
    patterns = ["a, S, 22", "d, d, 4", "a, S, 25"]
    Sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (a, S, 25)(e, c, 4)(b, S, 24) -- (0, 1, 3) --

Discussions similaires

  1. Utiliser le Point (.) dans les regex
    Par LinkinSelim dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 19/06/2007, 19h25
  2. Réponses: 5
    Dernier message: 11/01/2007, 09h50
  3. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  4. Merci d'utiliser les TAG
    Par Cian dans le forum Etudes
    Réponses: 0
    Dernier message: 07/08/2003, 17h46
  5. Utiliser les frames
    Par laury dans le forum Composants VCL
    Réponses: 5
    Dernier message: 10/05/2003, 10h14

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