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 :

sous chaine python


Sujet :

Python

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut sous chaine python
    Bonjour,
    j'ai un petit souci.
    je souhaite rechercher une sous chaine dans une string.
    j'ai essayé la méthode find et re.search, ça marche mais pas totalement.
    je m'explique

    je recherche la sous chaine "public" dans une liste de mots composés.

    ma liste ["test python","test python","publications annulées","public averti"]

    moi ce que je souhaite, c'est savoir si le mot "public" est dans la liste.
    bon typiquement je parcours ma liste et je teste si "public" est une sous chaine de chaque élément.
    or avec find et search, il me sort "publications annulées" car il ya "public"ations (ce que je ne veux pas) et "public averti" ce que je veux.

    vous savez comment forcer la recherche précise ?

    merci

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

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Par défaut
    Salut,
    je recherche la sous chaine "public" dans une liste de mots composés.
    moi ce que je souhaite, c'est savoir si le mot "public" est dans la liste
    C'est pas la même chose...

    Si tu veux le mot exact, tu peux parcourir chaque element de ta liste, créer une nouvelle liste en séparant cet element par l'espace puis chercher si 'public' est un element de ta nouvelle liste.

    C'est long à expliquer mais ca tiens sur une ligne avec une comprehension de liste.

    @+

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    oui, j'avais pensé à ça en splitant par l'espace.
    mais imagine le cas où tu as Côte d'or, je recherche le mot "or".
    je ne le splite plus par l'espace.
    y a plein de cas particulier.

    là je me rend compte que ça devient très complexe.

    je vais réfléchir à expliquer mon pb, car je me rends compte ce que je souhaite c'est vraiment complexe

    je te remercie

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    voici un ex :

    je recherche le mot "or" dans cette liste ["organigramme d'une société","Cote d'or"], là il doit me retourner vrai (à cause de Cote d'or)

    je recherche le mot "assises" dans cette liste ["cours d'assises", "exemple d'assises"], là il doit me retourner vrai (à cause d'exemle d'assises)

    je recherche le mot "public" dans cette liste ["publications trop tard", "test python"], il doit me retourner faux.

    il y a plusieurs cas, notamment les noms composés avec les tirets, les apostrophes, espaces. (je pense qu'il y a que ces 3 cas là)

    donc si vous voyez une solution, je suis preneur

    merci

  5. #5
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Voici une fonction qui fait ce tu veux (je pense):
    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
     
    import re
     
    def liste_contient_mot(mot, L):
        rx = re.compile(r'\b%s\b' % mot)
        return any(rx.search(e) for e in L)
     
     
    >>> liste_contient_mot('public', ['foo', 'bar'])
    False
     
    >>> liste_contient_mot('public', ['foo', 'bar', 'publications diverses'])
    False
     
    >>> liste_contient_mot('public', ['foo', 'bar', 'publications diverses', 'public averti'])
    True
    Ça requiert Python 2.5+ pour la fonction any(). Remarque qu'elle est facile à écrire, donc tu peux la définir toi même si tu as besoin que ce soit compatible avec des versions plus anciennes.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    ok, je vais tester!!
    je te tiens au courant

    merci

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    merci, c nikel ça marche !!!!
    même avec les tirets et guillements comme par ex :


    print liste_contient_mot('assise', ['foo', 'bar', 'organisation', "cours-assise"])
    >True
    print liste_contient_mot('assise', ['foo', 'bar', 'organisation', "cours d'assise"])
    >True
    print liste_contient_mot('assise', ['foo', 'bar', 'organisation', "cours-assises"])
    >False

    Par contre, j'ai python 2.4 (université), j'ai réecris la fonction any

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    def liste_contient_mot(mot, L):
        rx = re.compile(r'\b%s\b' % mot)
        return any(rx.search(e) for e in L)
     
    def any(liste):
             for x in liste:
                 if x:
                     return True
             return False
    merci beaucoup pour ton aide

  8. #8
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Pas de quoi.

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    je viens d'agrandir mon texte !!!!, et malheureusement, il me sort cette erreur :

    sre_constants.error: unbalanced parenthesis

    lors de mon parcours du texte, j'ai un token : CD-ROM (

    et là, l'expression régulière décrit ci dessus ne passe plus !!!!

    n'étant pas un spécialiste des expressions régulières, tu sais comment on fait pour prendre en compte les parenthèses ?

    en gros

    print liste_contient_mot('CDROM(', ['Il y a un CDROM(']) ==> sre_constants.error: unbalanced parenthesis

    j'ai testé, c'est la parenthèse qui est dans le premier argument qui pose problème, le second ne gène pas

  10. #10
    Membre émérite

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Par défaut
    Pour ça, il y a re.escape, qui permet d'échapper tous les caractères spéciaux

  11. #11
    Membre Expert
    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
    Par défaut Perplexité
    Pour comprendre la regex de GnuVince, j'ai lu la définition de \b et le début de cette définition me surprend:
    «Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of alphanumeric or underscore characters, so the end of a word is indicated by whitespace or a non-alphanumeric, non-underscore character.»

    «Matches the empty string,...» :
    Est-ce à dire qu'il faut voir une chaine de caractères comme une succession de caractères séparés par des empty strings '' ??
    Ou est-ce une façon maladroite mais condensée de dire que \b détecte la contigüité d'un caractère alphanumérique ou l'undescore et n'importe quel autre caractère n'étant ni alphanumérique ni l'underscore ??

    Dans le premier cas, cela me conduit à imaginer la succession des bits qui représente dans la machine une chaine de caractères comme une alternance de bits représentant des caractères et de bits représentant l'empty string ''.
    Et ça me parait bizarre comme idée.

    See what I mean ?

  12. #12
    Membre émérite

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Par défaut
    Il s'agit bien de tester la contiguïté avec un caractère ne faisant pas partie d'un mot, et il ne recouvre aucun caractère (ce qui explique le "matches the empty string")

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    merci, je vais tester le re.escape pour voir!!!
    je te tiens au courant

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    je viens de tester avec re.escape.
    ça ne marche pas :
    j'ai changé le bout de code ci dessus
    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
     
    def liste_contient_mot(mot, L):
        rx = re.compile(r'\b%s\b' % re.escape(mot))
        newList=[]
       #j'ai rajouté cette boucle pour pouvoir comparer correctement le mot recherché avec les éléments de la liste
       for i in L:
            newList.append(re.escape(i))
        return any(rx.search(e) for e in newList)
     
    def any(iterable):
             for element in iterable:
                 if element:
                     return True
             return False
     
    print liste_contient_mot('CDRM(', ['foo', 'bar', 'organisation', 'CDRM('])
    >> False, alors que ça devrait être True

  15. #15
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Fais pas un newList. Fais juste utiliser re.escape sur mot.

  16. #16
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    J'ai une autre proposition basée sur find.

    Il faut commencer par mieux définir ce qu'on cherche. J'ai considéré, d'après tes exemples, que le mot est trouvé quand:

    * le 1er caractère du mot est le 1er caractère de la chaine OU est précédé par un espace ou une apostrophe
    * ET
    * le dernier caractère du mot est le dernier caractère de la chaine OU est suivi par un espace

    Ce qui donne comme code:

    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
     
    def liste_contient_mot(mot, L):
        lg = len(mot)
        for ch in L:
            k1 = ch.find(mot)
            if k1>=0:
                k2 = k1+lg
                if (k1==0 or ch[k1-1] in " '") and \
                   (k2==len(ch) or ch[k2] in " "):
                    return True
        return False
     
    L = ["organigramme d'une société","Cote d'or"]
    mot = "or"
    print liste_contient_mot(mot, L)               
     
    L = ["cours d'assises", "exemple d'assises"]
    mot = "assises"
    print liste_contient_mot(mot, L)
     
    L = ["publications trop tard", "test python"]
    mot = "public"
    print liste_contient_mot(mot, L)
    Ce qui donne bien True, True et False.

    Tu peux ajouter d'autres conditions de réussite, par exemple que le dernier caractère du mot puisse être suivi par un caractère de ponctuation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ... or ch[k2] in " ,.;:?!" ...
    Tu peux aussi ajouter comme condition que l'apostrophe qui précède le mot n'est testée que si son 1er caractère est une voyelle "aeiouy" (en ajoutant les accents!):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (k1==0 or ch[k1-1]==" " or (ch[k1] in "aeiouy" and ch[k1-1]=="'")) and \
    Tyrtamos

    Edit: petit complément, peut-être faut-il ajouter le "h" au test des voyelles, afin de trouver le mot "heure" dans la chaîne "mettre à l'heure".

  17. #17
    Membre émérite

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Par défaut
    Pour ma part, je dirais que c'est le \b qui pose problème, puisqu'il teste toujours la contiguïté entre un \w et un \W, donc je pense qu'il vaudrait mieux partir sur une autre piste, ne serait-ce que de matcher un \W avant et après (sans oublier d'ajouter un caractère au début et à la fin de ta chaîne pour que ça marche au niveau des bords)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def liste_contient_mot(mot, L):
        rx = re.compile(r'\W%s\W' % re.escape(mot))
        return any(rx.search('\0' + e + '\0') for e in L)

  18. #18
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    @oiffrig

    t balaise !!!!

    ça marche sur quelques tests, il faudra que j'essaie sur un gros corpus, mais y a pas de raison pour que ça ne marche pas.

    merci beaucoup!!!!!

  19. #19
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    tu sais s'il existe un moyen de créer une graph structur en python.
    en fait je pourrai utiliser un tableau à deux dimensions.

    J'ai par ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Mot    A     B    C   
     
    A       10    5    2
     
    B       5      2    8
     
    C       2      8    11

    ça veut que le mot A apparait avec B 5 fois etc.......
    je l'ai réalisé (avec un fichier 100Ko) mais le souci, c'est le fichier que je dois utiliser a au moins 1 millions de mots (c un minimum je crois) lol, mon fichier fait 150Mo

    Donc j'aimerai transformer cette matrice en graphe
    pour que ça devienne du genre arete(A,B) = 5

    j'ai cherché un module graph dans python mais en vain!!!!!

    merci d'avance

  20. #20
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    358
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 358
    Par défaut
    finalement, c bon, je vais gérer avec des dictionnaires de dictionnaires

    c bon maintenant !!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Rechercher une sous chaine dans une chaine
    Par annedjomo dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 04/02/2005, 10h36
  2. Rechercher une sous chaine dans une chaine
    Par Oluha dans le forum ASP
    Réponses: 4
    Dernier message: 03/02/2005, 14h39
  3. Extraction de sous-chaine dans une chaine
    Par ma2th dans le forum C
    Réponses: 7
    Dernier message: 07/05/2004, 12h42
  4. Réponses: 10
    Dernier message: 24/02/2004, 12h28
  5. [sous-chaine] Avec strpos ou substring ??
    Par terziann dans le forum SQL Procédural
    Réponses: 5
    Dernier message: 17/07/2003, 15h28

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