Créer listes par longueur de mots

Créer listes par longueur de mots - Python - Programmation

Marsh Posté le 11-01-2015 à 18:02:34    

Bonjour,
 
Je souhaite faire un programme qui d'abord :
- prend le texte d'un fichier.txt et le place dans une liste
- remplace les accents par les minuscules équivalentes
- enlève la ponctuation
- convertit la liste en minuscule
- sépare les mots
- tri les mots par longueur (puis ordre alphabétique)
 
Voici mon programme :
 

Code :
  1. fichier = open('fichier_a_convertir.txt','r')     #ouvre fichier
  2. chaine = fichier.read()                           #lire le contenu du fichier
  3. fichier.close()                                   #fermer fichier
  4. #enlever les accents
  5. chaine = chaine.replace("é","e" )
  6. chaine = chaine.replace("è","e" )
  7. chaine = chaine.replace("ê","e" )
  8. chaine = chaine.replace("à","a" )
  9. chaine = chaine.replace("ï","i" )
  10. chaine = chaine.replace("î","i" )
  11. chaine = chaine.replace("ù","u" )
  12. #enlever la ponctuation
  13. longueur = len(chaine)                            #longueur du paragraphe
  14. chaine1 = ''                                      #initialisation du texte converti
  15. for i in range(longueur):
  16.     if ord(chaine[i])==32 or ord(chaine[i])>=65 and ord(chaine[i])<=90 or ord(chaine[i])>=97 and ord(chaine[i])<=122:
  17.         #ASCII = 32 → espace / 65~90 → A...Z / 90~122 → a...Z
  18.         chaine1 = chaine1 + chaine[i]
  19.     else:
  20.         chaine1 = chaine1 + " "
  21.         i = i+1
  22. chaine1 = chaine1.lower()                         #mettre le texte en minuscule
  23. liste = chaine1.split()                           #classer chaque mot dans une liste
  24. liste.sort()                                      #tri alphabétique
  25. print(liste)                                      #afficher cette liste


 
Or le programme m'affiche :
['a', 'a', 'a', 'a', 'amazone', 'aux', 'avoir', 'ces', 'craindre', 'de'...
 
Ce que j'aimerai, c'est qu'il affiche :
['a', 'a', 'a', 'a', 'ces', 'de', 'aux', 'avoir', 'amazone', 'craindre'...
 
Ensuite, est-il possible de classer les mots par longueur dans des listes différentes, exemple:
 
Une liste contenant tous les mots de longueur 1
puis de longueur 2
puis de longueur 4 (s'il n'y a pas 3...)
 
Merci de votre lecture.

Reply

Marsh Posté le 11-01-2015 à 18:02:34   

Reply

Marsh Posté le 11-01-2015 à 21:15:11    

Déjà, réécrire ton code d'une manière plus pythonesque :
 

Code :
  1. equiv = {
  2.             "â" : "a",
  3.             "é" : "e",
  4.         }
  5. characters_ok = (" ",
  6.                  "a", "b", "c", "d", "e", "f", "g", "h", "i",
  7.                  "j", "k", "l", "m", "n", "o", "p", "q", "r",
  8.                  "s", "t", "u", "v", "w", "x", "y", "z",
  9.                  "A", "B", "C", "D", "E", "F", "G", "H", "I",
  10.                  "J", "K", "L", "M", "N", "O", "P", "Q", "R",
  11.                  "S", "T", "U", "V", "W", "X", "Y", "Z",)
  12. with open("src.txt",'r') as src_file:
  13.     content = src_file.read()
  14.     for src, dest in equiv.items():
  15.         content = content.replace(src, dest)
  16.     content = "".join(char for char in content if char in characters_ok)
  17.     content = content.lower()
  18.     liste = content.split()
  19.     liste.sort()
  20.     print(liste)


---------------
rule #1 : trust the python
Reply

Marsh Posté le 11-01-2015 à 21:24:32    

Pour le reste, je n'ai pas compris le rapport entre l'énoncé du problème et le résultat que tu nous montres; pour ma part, voici comment je procéderais, en ajoutant au début de chaque mot un préfixe numérique égal à la taille du mot. Ainsi .sort() trie d'abord la taille, puis le mot lui-même.
 

Code :
  1. equiv = {
  2.             "â" : "a",
  3.             "é" : "e",
  4.         }
  5. characters_ok = (" ",
  6.                  "a", "b", "c", "d", "e", "f", "g", "h", "i",
  7.                  "j", "k", "l", "m", "n", "o", "p", "q", "r",
  8.                  "s", "t", "u", "v", "w", "x", "y", "z",
  9.                  "A", "B", "C", "D", "E", "F", "G", "H", "I",
  10.                  "J", "K", "L", "M", "N", "O", "P", "Q", "R",
  11.                  "S", "T", "U", "V", "W", "X", "Y", "Z",)
  12. with open("src.txt",'r') as src_file:
  13.     content = src_file.read()
  14.     for src, dest in equiv.items():
  15.         content = content.replace(src, dest)
  16.     content = "".join(char for char in content if char in characters_ok)
  17.     content = content.lower()
  18.     # liste = ['0001a', '0002de', '0005avoir']
  19.     liste = ["{0:04}".format(len(word)) + word for word in content.split()]
  20.     liste.sort()
  21.     # enlever le préfixe numérique à chaque mot :
  22.     liste = [word[4:] for word in liste]
  23.     print(liste)


 
Qu'en penses-tu ?


---------------
rule #1 : trust the python
Reply

Marsh Posté le 11-01-2015 à 21:35:32    

Bah déjà merci !
 
Mais je suis débutant en python et ne connais donc pas l'ensemble des fonctions que tu utilises :
 
.items() → qu'est-ce ?
 
d'où vient la variable dest ?
 

Code :
  1. content = "".join(char for char in content if char in characters_ok)

Cette ligne ajoute que les lettres contenues dans characters_ok ?
 

Code :
  1. liste = ["{0:04}".format(len(word)) + word for word in content.split()]

Que fait cette ligne ?

Reply

Marsh Posté le 11-01-2015 à 21:47:36    

suizokukan a écrit :

pour ma part, voici comment je procéderais, en ajoutant au début de chaque mot un préfixe numérique égal à la taille du mot. Ainsi .sort() trie d'abord la taille


Ya plus besoin de faire du DSU hein (et quand bien même c'était à base de tuples), tu peux filer une fonction key= à sort ou sorted qui calcule la clé de tri:

Code :
  1. >>> words = ['a', 'a', 'a', 'a', 'amazone', 'aux', 'avoir', 'ces', 'craindre', 'de']
  2. >>> sorted(words, key=lambda w: (len(w), w))
  3. ['a', 'a', 'a', 'a', 'de', 'aux', 'ces', 'avoir', 'amazone', 'craindre']
 
suizokukan a écrit :

Qu'en penses-tu ?


Les remplacements de caractères codés en dur c'est quand même cradox, perso j'utiliserais unicodedata pour faire une décomposition canonique et ne garder que les caractères de base:

 
Code :
  1. import unicodedata
  2.  
  3. words = ["été", "enlève", "être"]
  4.  
  5. def unaccent(word):
  6.    return ''.join(
  7.        letter
  8.        for letter in unicodedata.normalize("NFD", word)
  9.        if not unicodedata.combining(letter)
  10.    )
  11.  
  12. print(list(map(unaccent, words)))


=> ['ete', 'enleve', 'etre']

 

Et si les libs externes sont permises, Unidecode c'est encore mieux.


Message édité par masklinn le 11-01-2015 à 21:51:57

---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box, and replicate and expand beyond their wildest dreams by throwing away the limits imposed by overbearing genetic r
Reply

Marsh Posté le 11-01-2015 à 21:51:20    

.items() → "d".items() renvoie une liste de couple (clef, valeur) du dictionnaire "d". La doc est ici : https://docs.python.org/3.4/library/stdtypes.html . Par exemple, j'aurais pu écrire :

Code :
  1. for key, value in d.items()


ou encore

Code :
  1. for k, v in d.items()


 
Le

Code :
  1. content = "".join(char for char in content if char in characters_ok)

est plus compliqué à comprendre. L'idée est d'éviter en Python d'ajouter les chaînes les unes aux autres avec "+" ou "+=", car c'est lent. Il est plus rapide de créer une liste :

Code :
  1. liste = ['a', 'b']


 
... de la manipuler en ne retenant que les caractères autorisés :
 

Code :
  1. liste2 = [car for car in liste if car in caractères_autorisés]


 
... et enfin de transformer cette liste en chaîne de caractères en concaténant chaque élément, par exemple avec un "*" :
 

Code :
  1. "*".join(list2)


renverra quelque chose comme "*a*b", tandis que :

Code :
  1. "".join(list2)


renverrait "ab"
 
S'agissant de

Code :
  1. liste = ["{0:04}".format(len(word)) + word for word in content.split()]

, pour chaque word dans content.split(), je l'ajoute à une nouvelle "liste" mais je fais d'abord précéder ce word de "{0:04}".format(len(word)).
"{0:04}".format(len(word)) est une manière de dire : crée une chaîne de caractères contenant une chaîne vide avec un argument nommé {0}, de quatre chiffres de longueur avec remplissage par des zéros s'il en manque ('0001' et non '1'). Le {0} est remplacé par len(word), soit la longueur de word.


Message édité par suizokukan le 11-01-2015 à 21:56:27

---------------
rule #1 : trust the python
Reply

Marsh Posté le 11-01-2015 à 21:55:08    

> Pito2901, je souscris complètement au code de Masklinn. Ici, DSU=http://en.wikipedia.org/wiki/Disjo [...] _structure .


---------------
rule #1 : trust the python
Reply

Marsh Posté le 11-01-2015 à 23:22:47    


Presque, c'est decorate-sort-undecorate :D


---------------
I mean, true, a cancer will probably destroy its host organism. But what about the cells whose mutations allow them to think outside the box, and replicate and expand beyond their wildest dreams by throwing away the limits imposed by overbearing genetic r
Reply

Marsh Posté le 12-01-2015 à 17:42:42    

Oups, merci, je ne connaissais pas.


---------------
rule #1 : trust the python
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed