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 :

Opération sur une chaine


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut Opération sur une chaine
    Bonsoir à tous,

    Je planche actuellement sur une fonction qui me permettrait de supprimer certaines voyelles (et semi voyelles ou consonnes muettes) d'une chaine de caractères, puis de convertir les lettres restantes en chiffres (mais ce n'est pas pour tout de suite ).


    Voici ma fonction et mon problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def voyelles(chaine):
    bib1=["AEIOUYWH"]
    bib2=[""]
    i=0
    for mot in bib1:
    repl=bib2[i]
    for lettre in mot:
    chaine=chaine.replace(lettre,repl)
    i+=1
    return chaine
    J'aimerais faire en sorte que la fonction ignore la première lettre de la chaine et la conserve même si c'est une voyelle mais je sèche...

    J'ai essayé plusieurs choses, je ne sais pas trop si je dois rajouter une condition ou un while.

    J'ai tenté aussi de rajouter par exemple un for lettre in mot[1:]:

    Ça marche et garde le second caractère même si c'est une voyelle, mais si j'essaie [0:] (pour faire à partir du second caractère et laisser le premier de coté) cela ne fonctionne plus et j'ai du mal à saisir pourquoi.

    Je dois être un peu fatiguée, je sais que tout cela est simpliste mais je vous remercie par avance pour votre aide.



  2. #2
    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
    Ta fonction est manifestement destinée à évoluer en recevant des éléments supplémentaires dans bib1 et bib2.
    C'est pourquoi j'augmente artificiellement leur contenu pour réfléchir plus aisément:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        bib1=["AEI","OU","YWH"]
        bib2=["","",""]
    Ceci permet de se rendre compte que l'état actuel de ta fonction dans lequel les listes bib1 et bib2 comptent chacune 1 seul élément trouble la vision de ce qu'il y a à faire et que cela ne t'a pas permis de t'apercevoir que , non, ta fonction ne marche pas: en réalité, elle n'itère pas.
    Si elle tourne, c'est uniquement parce qu'il n'y a qu'un seul élément dans bib1 et dans bib2.

    Avant de penser à ton problème de [1:] ,il faut donc faire en sorte que la fonction marche vraiment.

    Le trouble provient du fait que tu as besoin d'utiliser successivement des couples (el1,el2) dans lesquels el1 est de bib1 et el2 de bib2 et que tu penses l'itération à la fois comme un parcours de bib1 par éléments (for mot in bib1) et comme un parcours de bib2 par indice (le i de bib2[i]) . Mais évidemment el1 et el2 étant en correspondance, il n'est pas possible de faire ce qui est en réalité une seule itération en utilisant deux moyens. Il te faut donc choisir:

    - soit itérer selon les éléments de bib1, mais ça donne quelque chose d'inutilement compliqué:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ch = 'BEFORE THE END OF THE DAY, THE CAT WAS DEAD'
     
    def voyelles(chaine):
        bib1=["AEI","OU","YWH"]
        bib2=["","",""]
        for mot in bib1:
            i = bib1.index(mot)
            repl=bib2[i]
            for lettre in mot:
                chaine=chaine[0] + chaine[1:].replace(lettre,repl)
        return chaine
     
    print ch
    print voyelles(ch)
    - soit itérer selon un indice jouant un rôle commun dans les deux listes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ch = 'BEFORE THE END OF THE DAY, THE CAT WAS DEAD'
     
    def voyelles(chaine):
        bib1=["AEI","OU","YWH"]
        bib2=["","",""]
        for i in xrange(0,len(bib1)):
            mot,repl = bib1[i],bib2[i]
            for lettre in mot:
                chaine=chaine[0] + chaine[1:].replace
        return chaine
     
    print ch
    print voyelles(ch)

    J'ai aussi pensé à un autre algorithme:
    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
    def voy(chaine):
        bib1=["AEI","OU","YWH"]
        bib2=["","",""]
        out = chaine[0]
        for i in xrange(0,len(bib1)):
            mot,repl = bib1[i],bib2[i]
            for caractere in chaine[1:]:
                if caractere in mot:
                    out += repl
                else:
                    out += car
        return chaine
     
    print ch
    print voyelles(ch)
    qui peut se simplifier en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def voy(chaine):
        bib1=["AEI","OU","YWH"]
        bib2=["","",""]
        out = chaine[0]
        for i in xrange(0,len(bib1)):
            for caractere in chaine[1:]:
                if caractere in bib1[i]:
                    out += bib2[i]
                else:
                    out += car
        return chaine
    Il y a plein d'autres algorithmes envisageables. Mais pour rester sur le tien, je pense que tu as tout avantage à utiliser un dictionnaire au lieu de deux listes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ch = 'BEFORE THE END OF THE DAY, THE CAT WAS DEAD'
     
    def voyelles(chaine):
        repl = {"AEI":"","OU":"","YWH":""}
        for mot in repl:
            for lettre in mot:
                chaine=chaine[0] + chaine[1:].replace(lettre,repl[mot])
        return chaine
     
    print ch
    print voyelles(ch)
    -------------------------

    En fait, concernant l'algorithme, étant donné ce que tu souhaite comme développement ultérieur, je pense que LA solution est d'utiliser translate().
    Il se trouve que quelqu'un a demandé des renseignements sur cette fonction il y a 4 jours:
    http://www.developpez.net/forums/d69...nne-translate/

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Juste une petite addition. Au lieu de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for i in xrange(0,len(bib1)):
        mot,repl = bib1[i],bib2[i]
        ...
    La fonction zip est là pour ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for mot, repl in zip(bib1,bib2):
        ...
    Ici, "zip" est sans doute plus adapté, mais je signale aussi la fonction enumerate:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for i, mot in enumerate(bib1):
        repl = bib2[i]
        ...

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Bonsoir à tous =)

    Merci pour vos réponses !
    J'ai finalement choisi le dictionnaire comme montrait Eyquem.

    Pour ma première fonction, tu disais qu'elle fonctionnait uniquement car il n'y avait un seul élément dans les listes, mais je l'utilisais également pour le codage en chiffre ou la suppression des accents avec plusieurs éléments (voir dans le script plus bas) et j'avais l'impression qu'elle marchait pourtant selon les tests que j'ai pu faire.
    Ce n'était qu'une impression ?

    La version définitive de la chose qui est un petit Soundex simplifié :

    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
    def soundex(chaine):
    # Remplacement des caractères accentués et suppression des espaces éventuels
        repl = {"âäà":"a","éèêë":"e","îï":"i","ôö":"o","ûùü":"u","ç":"c"," ":""}
        for mot in repl:
            for lettre in mot:
                chaine=chaine[0]+chaine[1:].replace(lettre,repl[mot])
        chaine=chaine.upper()       #Passage en majuscule
    #Suppression des voyelles, w et h, en gardant la première lettre
        repl = {"AEI":"","OU":"","YWH":""}
        for mot in repl:
            for lettre in mot:
                chaine=chaine[0]+chaine[1:].replace(lettre,repl[mot])
    #Remplacement des lettres restantes par le code associé
        repl = {"BP":"1","CKQ":"2","DT":"3","L":"4","MN":"5","R":"6","GJ":"7","XZS":"8","FV":"9"}
        for mot in repl:
            for lettre in mot:
                chaine=chaine[0]+chaine[1:].replace(lettre,repl[mot])
    #Suppression des doublons
        chaine2=chaine[0]
        for n in chaine[1:]:
            if chaine2[-1] != n:
                chaine2 += n
    #Mise en forme du code sous forme Lettre chiffre chiffre chiffre
        while len(chaine2)<4:
            chaine2+="0"
        return chaine2[:4]

    J'aimerais faire en sorte que la fonction puisse être appliquée à des mots lus dans un fichier texte.
    J'ai testé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    import codecs
    f=codecs.open('names.txt','r',encoding='iso-8859-1')
    data=f.readlines()
    for word in data:
        soundex(word)
    Mais je ne sais pas trop si cela fonctionne car j'ai visiblement des erreurs d'encodage qui m'empêchent d'avoir un résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Traceback (most recent call last):
      File "D:/Cours/Linguistique et Informatique/S2/Exos/soundexnew.py", line 32, in <module>
        soundex(word)
      File "D:/Cours/Linguistique et Informatique/S2/Exos/soundexnew.py", line 6, in soundex
        chaine=chaine[0]+chaine[1:].replace(lettre,repl[mot])
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    En ouvrant le fichier de cette manière, Python te renvoie des chaînes en unicode, donc tu devrais aussi définir tes autres chaînes en unicode, au moins pour les chaînes qui contiennent des caractères non-ASCII.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    repl = {u"âäà":"a",u"éèêë":"e",u"îï":"i",u"ôö":"o",u"ûùü":"u",u"ç":"c"," ":""}
    Et t'assurer que ton éditeur sauvegarde bien le script dans le même codec (iso-8859-1).

    Enfin je crois... C'est toujours pénible les problèmes d'encodage...

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 13
    Par défaut
    Effectivement d'après ce que j'ai vu sur le net, ça a l'air vraiment d'être le bazar l'encodage/décodage

    En tout cas, avec l'ajout de l'unicode dans les chaines contenant les non ASCII et d'une entête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    # -*- coding: iso-8859-1 -*-
    en haut du script, ça à l'air de fonctionner nickel.

    Merci bien !

    Par contre, par rapport aux résultats affichés j'ai un souci avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #Mise en forme du code sous forme Lettre chiffre chiffre chiffre
        while len(chaine2)<4:
            chaine2+="0"
        return chaine2[:4]
    Ca fonctionne correctement dans l'idle quand je teste avec des chaines lambda, mais quand il s'agit des noms lus dans le fichier texte, visiblement cela ne veut plus marcher.
    Je ne vois pas trop pourquoi...

Discussions similaires

  1. [Tableaux] Opérations sur une chaine
    Par Ben-o dans le forum Langage
    Réponses: 6
    Dernier message: 09/12/2008, 16h47
  2. fread sur une chaine de caractere ?
    Par Battosaiii dans le forum C
    Réponses: 17
    Dernier message: 18/03/2006, 12h50
  3. Masque sur une chaine
    Par Weedo dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 10/01/2006, 11h32
  4. Erreur de segmentation sur une chaine en récursif...
    Par laurent_ifips dans le forum C
    Réponses: 12
    Dernier message: 13/12/2005, 16h04
  5. [Débutant][String] Opérations sur une chaîne
    Par gandalf_le_blanc dans le forum Général Java
    Réponses: 8
    Dernier message: 08/06/2004, 11h59

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