Bonjour,
je voudrais passer de "bla bla 34 5 6 78 9 0 bla bla" à "bla bla 34567890 bla bla".
Toute info. est la bienvenue.
Bonjour,
je voudrais passer de "bla bla 34 5 6 78 9 0 bla bla" à "bla bla 34567890 bla bla".
Toute info. est la bienvenue.
Bonjour,
Ce n'est peut-être pas très subtil, mais ça marche:
Le principe n'est pas très compliqué:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 import re def remplace(matchobj): return matchobj.group(1) ch = "bla bla 34 5 6 78 9 0 bla bla" res = re.sub(r"([0-9]) (?=[0-9])", remplace, ch) print res bla bla 34567890 bla bla
Si on oublie le (?=), la recherche avance d'un caractère de plus, et comme elle se fait sans recouvrement, l'espace après le '5' est ignoré.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 ([0-9]) <== un chiffre <== un espace (?=[0-9]) <== un chiffre mais ne "consomme pas" un caractère de recherche
La fonction remplace() construit la chaine de remplacement à partie du 1er groupe trouvé qui est le seul 1er caractère du motif (c'est pour trouver ce groupe qu'il est entre parenthèses).
Tyrtamos
S’il y a plusieurs blancs entre les chiffres, ta regex ne marche pas, tyrtamos. Il faut ajouter une étoile après le blanc dans ta RE.
Mais rambc n’a pas précisé s’il peut y avoir plusieurs blancs entre les chiffres. Si ce n’est pas le cas, il ne faut pas ajouter une étoile.
En tous cas, ta méthode de traitement des blancs inter-chiffres les uns après les autres est plus longue qu’une méthode basée sur le traitement des chaînes de chiffres matchantes d’un seul coup.
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 import re from time import clock ch = '''jhgjhgasd 563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg 564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhfyyt poiu 75 6 ljhf 8d89 34h5t 673 dj47 478 3 222 390 nytir''' te = clock() for i in xrange(10000): # methode replace sur chaines matchantes ch = re.sub('\d[\d ]*\d',lambda m: m.group().replace(' ',''),ch) tf = clock() print '- methode replace sur chaines matchantes \n',tf - te,'secondes' print ch ch = '''jhgjhgasd 563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg 564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhfyyt poiu 75 6 ljhf 8d89 34h5t 673 dj47 478 3 222 390 nytir''' te = clock() for i in xrange(10000): # methode tyrtamos res = re.sub(r"([0-9]) (?=[0-9])", lambda m: m.group(1), ch) tf = clock() print '\n- methode tyrtamos \n',tf - te,'secondes' print res ch = '''jhgjhgasd 563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg 564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhfyyt poiu 75 6 ljhf 8d89 34h5t 673 dj47 478 3 222 390 nytir''''' te = clock() for i in xrange(10000): # methode tyrtamos avec etoile ajoutee dans la RE res = re.sub(r"([0-9]) *(?=[0-9])", lambda m: m.group(1), ch) tf = clock() print '\n- methode tyrtamos avec etoile ajoutee dans la RE \n',tf - te,'secondes' print res
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 - methode replace sur chaines matchantes 1.87107579315 secondes jhgjhgasd 563647657hhdhgfgf 67577434lklkkdf hghg 564758 lkiurr sss 4453234 lkjhfyyt poiu 756 ljhf 8d8934h5t 673 dj474783222390 nytir - methode tyrtamos 2.59343184678 secondes jhgjhgasd 563647657hhdhgfgf 67577434lklkkdf hghg 564758 lkiurr sss 4453 234 lkjhfyyt poiu 756 ljhf 8d8934h5t 673 dj47 4783 222 390 nytir - methode tyrtamos avec etoile ajoutee dans la RE 5.32312123468 secondes jhgjhgasd 563647657hhdhgfgf 67577434lklkkdf hghg 564758 lkiurr sss 4453234 lkjhfyyt poiu 756 ljhf 8d8934h5t 673 dj474783222390 nytir
Merci. La 1ère méthode me convient.
Ce n'est pas mon genre du tout... Effectivement il peut y avoir plusieurs espaces.
Il me reste une dernière chose à faire, à savoir ajouter un espace entre un chiffre et une lettre pour au final passer de "abcde bjhjhgjg12345 7899900 dghdgsv 9000kjhskjhjq" à "abcde bjhjhgjg 123457899900 dghdgsv 9000 kjhskjhjq".
Je pourrais alors finaliser un petit script qui permet passer d'un nombre écrit, comme "deux cents trois", à sa traduction en chiffre, soit "203" avec mon exemple.
Effectivement, je n'avais pas pensé à lambda (merci eyquem!), ce qui permet d'éliminer la fonction remplace().
Mon expression se simplifie alors. J'y ai ajouté le traitement de plusieurs espaces (avec un '+' et pas un '*'):
Il est possible que je rattrape ainsi une partie du temps.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 res = re.sub(r"([0-9])[ ]+(?=[0-9])", lambda m: m.group(1), ch)
Je n'ai pas encore vu la suite.
Tyrtamos
Pour la deuxième fonctionnalité, le code suivant semble faire l'affaire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 #! /usr/bin/env python import re text = 'abcde bjhjhgjg12345 7899900 dghdgsv 9000kjhskjhjq' def myRemplaceFunction(match): textFound = match.group() if textFound[0] != ' ' and textFound[1] != ' ': textFound = textFound[0] + ' ' + textFound[1] return textFound print(re.sub('((\d\D)|(\D\d))', myRemplaceFunction, text))
1) Dans ton code,
si tu remplaces \D par [^\d ], le programme trouvera directement les successions de deux caractères ’un chiffre,un non-chiffre’ tous deux différents de blancs,
et tu n’auras plus besoin de test.
2) Ton code a un problème:
avec text = 'abcde bjhjhgjg12345 7899900 dgh6dgsv 9000kjhskjhjq'
le résultat est
abcde bjhjhgjg 12345 7899900 dgh 6dgsv 9000 kjhskjhjq
et non pas
abcde bjhjhgjg 12345 7899900 dgh 6 dgsv 9000 kjhskjhjq
3) Ton dernier code ne fait qu’une partie du travail, rambc, il n’y a plus l’élimination des blancs au sein d’une série de chiffres.
Pour ma part, j’ai changé de RE pour résoudre tous les problèmes à la fois.
Noter que si la chaîne examinée commence ou termine par un chiffre, il y aura introduction d’un blanc devant , ou à la fin du résultat, ce qui n’est peut être pas souhaité. Auquel cas, un petit strip() et il n’y aura plus de blanc, ni devant ni à la fin.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 dh = '''563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhf7yyt poiu 75 6 ljhf8d89 34h56t 673 dj47 478 3 222 390 ttdsdr''' dhmod = re.sub('(?<![\d ])[\d ]+(?![\d ])', lambda m: ' ' + m.group().replace(' ','') + ' ', dh) print dh print print dhmod
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhf7yyt poiu 75 6 ljhf8d89 34h56t 673 dj47 478 3 222 390 ttdsdr 563647657 hhdhgfgf 67577434 lklkkdf hghg 564758 lkiurr sss 4453234 lkjhf 7 yyt poiu 756 ljhf 8 d 8934 h 56 t 673 dj 474783222390 ttdsdr
Merci beaucoup c'est super.
Ma précédente RE réduit les séries de blancs à deux blancs
puisqu’on ajoute ’ ’ avant et après m.group().replace(' ','')
J’ai cherché le moyen de réduire ces séries à un seul blanc ’ ’ .
Ce n’est pas d’une importance énorme, mais c’est pour le fun et à titre d’exercice.
Voilà donc:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 import re dh = 'hghg564 75 8 lkiurr sss 445 3 2 34 lkj' print dh print print re.sub('(?<![\d ])[\d ]+(?![\d ])', lambda m: ' ' + m.group().replace(' ','') + ' ',dh) print print re.sub('(?<![\d ])(?:(\d)| )+(?![\d ])', lambda m: ' ' + m.group().replace(' ','') + len(m.groups('')[0])*' ',dh)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 hghg564 75 8 lkiurr sss 445 3 2 34 lkj hghg 564758 lkiurr sss 4453234 lkj hghg 564758 lkiurr sss 4453234 lkj
Comment, comment ?
Tu fais un split() après le nettoyage ??
Je parie que tu ne voulais insérer un blanc entre un chiffre et une lettre que pour pouvoir faire un split() !
Mais c’est affreusement dilatoire, ce genre de truc....
Il faut y aller plus direct ! Il fallait le dire plus tôt.
Si c’est bien ça, voici ce que je propose
- si tu veux obtenir la liste des séries de chiffres, expurgées de leurs blancs:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 import re dh = '''gfsde563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhf7yyt poiu 75 6 ljhf8d89 34h56t 673 dj47 478 3 222 390 ttdsdr56''' print dh print print [ m.group().replace(' ','') for m in re.finditer('(?<!\d)(\d[\d ]*)(?!\d)',dh) ]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 gfsde563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhf7yyt poiu 75 6 ljhf8d89 34h56t 673 dj47 478 3 222 390 ttdsdr56 ['563647657', '67577434', '564758', '4453234', '7', '756', '8', '8934', '56', '673', '474783222390', '56']
Nota Bene:
si tu n’as pas besoin de créer la liste en dur, tu peux même travailler directement à partir du générateur
( m.group().replace(' ','') for m in re.finditer('(?<!\d)(\d[\d ]*)(?!\d)',dh) )
Si tu veux itérer sur les chaînes de chiffres expurgées, tu fais
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 for m in re.finditer('(?<!\d)(\d[\d ]*)(?!\d)',dh) : utilisation de m.group().replace(' ','')
Python est simple.
- si tu veux obtenir la liste alternante des séries de chiffres (sans leurs blancs) et des autres parties de la chaîne (sans blancs de part et d’autre, de par l’action de strip() ):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 import re dh = '''gfsde563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhf7yyt poiu 75 6 ljhf8d89 34h56t 673 dj47 478 3 222 390 ttdsdr56''' print dh print print [ u.replace(' ','') if i%2==1 else u.strip() for i,u in enumerate(re.split('(?<!\d)(\d[\d ]*)(?!\d)',dh)) ]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 gfsde563 6 4765 7hhdhgfgf 6757 7 4 34lklkkdf hghg564 75 8 lkiurr sss 4 4 5 3 2 34 lkjhf7yyt poiu 75 6 ljhf8d89 34h56t 673 dj47 478 3 222 390 ttdsdr56 ['gfsde', '563647657', 'hhdhgfgf', '67577434', 'lklkkdf\nhghg', '564758', 'lkiurr sss', '4453234', 'lkjhf', '7', 'yyt\npoiu', '756', 'ljhf', '8', 'd', '8934', 'h', '56', 't', '673', 'dj', '474783222390', 'ttdsdr', '56', '']
Nota: si tu veux obtenir les parties non-chiffres dans leur intégralité, il ne suffira pas d’enlever le strip() car la RE comporte [\d ]* qui consomme des blancs tant qu’il y en a et donc la série non-chiffre qui suit une série chiffres est toujours dénuée de blanc en tête. M’enfin, là c’est de la chipoterie qui ne doit pas t’être très utile.
En fait j'ai besoin de passer de
à
Code : Sélectionner tout - Visualiser dans une fenêtre à part "30et un mille quatre cents quatre-vingt-onze millions soixante-et-onze"
Ceci me permet alors de renvoyer :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 ['30', 'et', 'un', 'mille', 'quatre', 'cents', 'quatre', 'vingt', 'onze', 'millions', 'soixante', 'et', 'onze']
C'est pour cela que je passe par un split().
Code : Sélectionner tout - Visualiser dans une fenêtre à part 31 491 000 071
ah lala....
Resultat
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 import re dh = "30et un mille quatre cents quatre-vingt-onze millions soixante-et-onze" print re.findall('((?<!\d)\d[\d ]*(?!\d)|[^ -]+)',dh)['30', 'et', 'un', 'mille', 'quatre', 'cents', 'quatre', 'vingt', 'onze', 'millions', 'soixante', 'et', 'onze']
NB
L'ordre est important dans la RE
print re.findall('([^ -]+|(?<!\d)\d[\d ]*(?!\d))',dh)
donne
Code : Sélectionner tout - Visualiser dans une fenêtre à part ['30et', 'un', 'mille', 'quatre', 'cents', 'quatre', 'vingt', 'onze', 'millions', 'soixante', 'et', 'onze']
Il n'y avait plus l'élimination des blancs dans une série de chiffres dans avec la précédente RE.
Et puis ’30et un ’ donnait ’30’,’et’,’un’
mais ’quatre600 cents’ donnait ’quatre600’,’cents’
Il fallait rajouter \d dans l’ensemble [^ -]
Quant à \d[\d ]* , ça permet de capturer précisément tout ce qui est série de chiffres et blancs et comme il n’est plus nécessaire de capturer les blancs qui précèdent ce genre de série ou les suivent, les look-ahead et look-behind assertions ne se justifient plus.
D’où une réécriture de la RE, dans un ordre qui n’importe pas cette fois, et qui j’espère sera cette fois la bonne
ou
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 import re dh = "vingt 30et un mille quatre60 0 cents quatre-vingt6 54-onze millions soixante-et-onze" print [ m.group().replace(' ','') for m in re.finditer('(\d[\d ]*|[^ \d-]+)',dh)]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 import re dh = "vingt 30et un mille quatre60 0 cents quatre-vingt6 54-onze millions soixante-et-onze" print map(lambda x: x.replace(' ',''),re.findall('(\d[\d ]*|[^ \d-]+)',dh))
resultat
['vingt', '30', 'et', 'un', 'mille', 'quatre', '600', 'cents', 'quatre', 'vingt', '654', 'onze', 'millions', 'soixante', 'et', 'onze']
J'ai dû faire un list(map(...)) car j'utilise des listes et des indices lors de la conversion.
Merci eyquem !
Peux-tu montrer ce que ça donne, stp ?
A priori, map( ) s’applique à une liste et on en obtient une liste. Dès lors, je ne vois pas trop pourquoi tu écris list( map(...) )
Par ailleurs, quand il intervient des indices, il faut penser à enumerate() qui est une fonction super-sympa.
En fait sous Python 2.6 il n'y a pas de souci. Or je développe sous Python 3 et là il faut utiliser list.
OK.
La fonction built-in map( ) retourne désormais un itérateur dans 3.1 alors qu’elle retournait une liste dans 2.6
Quant à la fonction imap() du module itertools dans 2.6 qui retournait un itérateur, elle a disparu de ce module dans 3.1.
Les fonctions map() et imap() du module multiprocessing persistent dans 3.1 comme elles l’étaient dans 2.6
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager