Tout est dans le titre.
Toute info. est la bienvenue.
Version imprimable
Tout est dans le titre.
Toute info. est la bienvenue.
Bonjour,
Selon la nature du texte, ce qui sépare les mots peut être plus varié qu'un simple espace. Auquel cas, je propose plutôt de passer par les expressions régulières.
Par exemple:
Le motif ici veut dire:Code:
1
2
3
4
5
6
7
8 import re motif = r"[ ]*[,;:.!? ][ ]*" print re.split(motif, "aaa , bbb;ccc. ddd, eee fff") ['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff']
- espace: zéro ou plus
- l'un des caractères suivants: ,;:.!? ou un espace
- espace: zéro ou plus
Si c'est du texte littéraire, il y a d'autres problèmes. Par exemple, l'apostrophe peut être soit un séparateur situé entre un article et un mot (ex: l'artiste) soit faire partie d'un mot (ex: aujourd'hui). Il faut voir aussi si on veut traiter les traits d'union de fin de ligne. Etc...
Tyrtamos
Il est possible de faire un regex plus simple grace au \b (word-boundary).
Ou encore, en incluant les apostrophes dans un motCode:
1
2
3
4
5 >>> import re >>> pat = re.compile(r'\b\w+\b') >>> motif = "Salut l'ami, comment va,pense;a-aller=chez)ton\nfrere" >>> pat.findall(motif) ['Salut', 'l', 'ami', 'comment', 'va', 'pense', 'a', 'aller', 'chez', 'ton', 'frere']
Code:
1
2
3 >>> pat = re.compile(r"\b[\w']+\b") >>> pat.findall(motif) ['Salut', "l'ami", 'comment', 'va', 'pense', 'a', 'aller', 'chez', 'ton', 'frere']
Moi je ne comprends pas ce que signifie "avancer mot par mot".
Surtout le terme "avancer..." 8O
Vos codes n'avancent pas, il renvoient chacun une liste.
S'agit il de faire quelque chose du genre
for mot in texte: sans traitement préalable du type split() pour isoler les mots ?
Ou bien de déterminer la liste des mots d'un texte par un traitement comme vous les proposez ?
On sait tous les difficultés que posent des problèmes liés au langage, surtout des problèmes posés de façon trop générale et floue: «Selon la nature du texte, ce qui sépare les mots peut être plus varié qu'un simple espace» tyrtamos
Je ne comprends pas qu'on puisse essayer de répondre à une question aussi vague. Ou mal posée.
Ceci dit sans vouloir froisser personne
Bonjour,
Pour "avancer mot par mot", il est toujours possible de gérer le déplacement d'un curseur qui progresse caractère par caractère. On peut même faire cela en utilisant la fin de ligne comme un séparateur supplémentaire, ce qui permettrait de traiter un fichier texte d'un seul coup.
La solution suivante utilise une classe, parce que ça permet de conserver l'emplacement du curseur d'un mot à l'autre. Et on utilise les possibilités d'itérateur avec les méthodes next() et __iter__(), et la fin de boucle avec le déclenchement de l'exception StopIteration.
Exemple d'utilisation (on pourrait aussi définir d'autres séparateurs à l'appel de la classe):Code:
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 class Mot(object): def __init__(self, chaine="", sep=" ,;.:!?\r\n"): self.ch = chaine self.lch = len(self.ch) self.sep = sep self.i1 = 0 self.i2 = 0 def __iter__(self): return self def next(self): # recherche du début du mot suivant self.i1 = self.i2 while True: self.i1 += 1 if self.i1>=self.lch: raise StopIteration if self.ch[self.i1] not in self.sep: break # recherche de la fin du mot suivant self.i2 = self.i1 while True: self.i2 += 1 if self.i2>=self.lch: break if self.ch[self.i2] in self.sep: break # retour du mot return self.ch[self.i1:self.i2]
Ce qui affiche:Code:
1
2
3
4
5
6
7 texte = """ ghureiv ryhe-iuzop geizoapn fieoznv thdizoqa, muezpoadtyiezmn,crfslqmur ;fiesqnvy!ieqz feiozqy eizo fgieo ga ntejuvn t nhdus : vghuris ?ghsd""" for mot in Mot(texte): print mot
A noter que si la chaine de séparateur transmise à l'appel se limite aux caractères de fin de ligne ("\r\n"), la boucle renvoie chaque ligne du texte.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 ghureiv ryhe-iuzop geizoapn fieoznv thdizoqa muezpoadtyiezmn crfslqmur fiesqnvy ieqz feiozqy eizo fgieo ga ntejuvn t nhdus vghuris ghsd
Il devrait aussi être possible d'utiliser une expression régulière pour identifier des séparateurs plus complexes, avec dans ce cas transmission d'un motif à l'appel, au lieu d'une chaine de séparateurs.
Pour pouvoir récupérer l'emplacement exact de chaque mot dans le texte, il faut faire un appel un peu différent:
Ce qui affichera:Code:
1
2
3
4 mot = Mot(texte) for x in mot: print x, mot.i1, mot.i2
TyrtamosCode:
1
2
3
4
5
6
7 ghureiv 1 8 ryhe-iuzop 9 19 geizoapn 20 28 ... vghuris 128 135 ghsd 137 141
A mon sens, ce n'est définitivement pas les séparateurs qu'il faut identifier, mais bien les caractères qui peuvent faire partie d'un mot. (Donc les lettres et éventuels @ ou autres).
De cette manière, on évite d'oublier de spécifier des séparateurs, ils sont tous implicites. Dans ta liste plus haut, il manque notamment les parenthèses et le slash.
à Antoine_935:
Ce n'est pas mon choix. Les séparateurs me semblent plus faciles à identifier. Mais le choix entre les 2 solutions peut dépendre du type de texte.
Tyrtamos
J'ai une solution beaucoup plus simple :D
Ce qui affiche comme précédemment:Code:
1
2
3
4
5
6
7
8
9
10
11 import re texte = """ ghureiv ryhe-iuzop geizoapn fieoznv thdizoqa, muezpoadtyiezmn,crfslqmur ;fiesqnvy!ieqz feiozqy eizo fgieo ga ntejuvn t nhdus : vghuris ?ghsd""" motif = r"([^ ,;:.!?\r\n]+)" for mot in re.finditer(motif, texte): print mot.group(1)
Le motif utilisé veut dire: au moins un de n'importe quel caractère autre qu'un séparateur.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 ghureiv ryhe-iuzop geizoapn fieoznv thdizoqa muezpoadtyiezmn crfslqmur fiesqnvy ieqz feiozqy eizo fgieo ga ntejuvn t nhdus vghuris ghsd
Comme précédemment, on peut récupérer à chaque boucle l'emplacement exact du motif trouvé avec mot.start(1) et mot.end(1).
Il faut, bien entendu, gérer les séparateurs pertinents en fonction du but recherché. On peut aussi, à l'inverse, chercher les mots à travers les caractères permis dans les mots, en laissant donc implicites les séparateurs. A mon avis, c'est le type de texte qui dira ce qu'il faut faire (code source d'un programme, texte littéraire multilingue en unicode, ...).
Tyrtamos
La question avait déjà été traitée, avec toutefois des solutions un peu différentes si je me rappelle bien...
http://www.developpez.net/forums/d69...rences-entier/
EDIT: En fait le but du thread est un peu différent, puisqu'il y est question de compter les répétitions de chaque mots présents dans le texte, mais l'identification des mots reste commun a ton objectif...
Je plussoie Eyquem !Citation:
Moi je ne comprends pas ce que signifie "avancer mot par mot".
Surtout le terme "avancer..."
Vos codes n'avancent pas, il renvoient chacun une liste.
Quant aux regex pour un pb aussi simple ...
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 def avance(S): i=0 while True: Mot='' while not S[i].isalpha(): i+=1 while S[i].isalpha(): Mot+=S[i] i+=1 yield Mot def main(): S=" Tra la la" A=avance(S) try: while True: print A.next() except IndexError: print "C'est fini" main()
Bonjour,
Comme la question de départ était très générale, chacun l'a interprété à sa sauce. Mais en fait, chaque solution est adaptée à un type de texte différent.
La solution basée sur le test des mots avec isalpha() ne détectera pas des mots comprenant:
'_', '0'..'9': comme dans les noms de variable d'un code source (et les nombres seront des séparateurs).
'@': comme dans une adresse email (ni d'ailleurs '<' et '>')
'-' (=tiret comme dans "presse-fruits"), ''' (apostrophe comme dans "aujourd'hui") comme dans un texte littéraire.
Par contre, il trouvera les caractères accentués.
En fait la "bonne solution" est celle qui s'adaptera le plus facilement à la "grammaire" du texte et à la méthode de traitement voulue.
Tyrtamos
Cela c'est très simple à régler:Citation:
La solution basée sur le test des mots avec isalpha() ne détectera pas des mots comprenant:
Ecrire une chaine ALPHA comprenant tous les caractères qu'on veut accepter, écrire une fonction de test 'IsIn' testant si un caractère est dans ALPHA, et remplacer la méthode isalpha par la fonction IsIn.
Mon intervention venait surtout à l'appui de la remarque de Eyquem qui signale que beaucoup de solutions retournent des listes sortes de 'explode' du texte à étudier, au lieu d'avancer effectivement sans stockage inutile de grosses structures. Ce qu'il faut retourner c'est un itérateur, pas une liste.
Voilà, c'était ça mon idée.Citation:
Ce qu'il faut retourner c'est un itérateur, pas une liste.
Mais je n'ai pas réussi à l'exprimer de cette façon précise et concise.
À mon avis le challenge est impossible à réaliser parce que
- d'un coté, comme le dit très bien tyrtamos,
- d'un autre coté, rambc a répondu «C'est cela l'idée.» à la questionCitation:
la "bonne solution" est celle qui s'adaptera le plus facilement à la "grammaire" du texte et à la méthode de traitement voulue
Autrement dit, il s'agit d'obtenir le son des notes d'un piano sans appuyer sur les touches.Citation:
S'agit il de faire quelque chose du genre
for mot in texte: sans traitement préalable du type split() pour isoler les mots ?
Les discussions sur le meilleur moyen d'y arriver risquent de durer.
Bonjour,
J'ai donné une solution plus haut avec les regex / "finditer" (message #10) et, effectivement, il est difficile de faire un code plus simple (3 lignes).
Cependant, cela nécessite que le traitement ne demande pas un changement de motif en cours de parcours en fonction de ce qu'on a déjà trouvé.
Dans ce dernier cas, on peut utiliser les regex mais avec gestion d'un index et passage de cet index à l'appel de search() ou de match() afin que la recherche du motif commence à partir de cet index. C'est un peu plus complexe (une douzaine de lignes) mais ça permet des changements "contextuels" du motif pendant le parcours du texte. Par exemple, pour parcourir une chaine de caractère dans un code source.
Mais, bien sûr, il ne s'agit pas d'être "pour" ou "contre" les regex. si on peut décrire ici toutes les solutions possibles (et c'est enrichissant), on ne peut pas juger de leur pertinence sans en connaitre plus sur le problème à résoudre.
Tyrtamos
Cette solution me plait bien...
Pour ou contre les regex ? :roll: Le gros intérêt des regex est de donner la possibilité à l'utilisateur et non plus au programmeur de définir ses types de mots. Sinon je dois avouer que je ne suis pas très fan des regex :oops: et que j'ai tendance à parcourir les chaînes directement. Cela ne m'empêche pas de vouloir comprendre comment fonctionne les regex.
Tu trouveras sur ce site un tutoriel réellement bien fait sur les regex. je suis sur qu'après avoir lu et intégré ce tuto tu seras un grand fan de regex :p
http://www.regular-expressions.info/