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

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
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


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
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