Salut,
j´aimerai couper ou formater le string suivant:
i='1.2.840.113747.20040531165138.3388.3000.672' de facon à avoir un nouveau string j='3000.672' ou j='3000.672'. Je ne voudrai pas considerer les chiffres d´avant.
Version imprimable
Salut,
j´aimerai couper ou formater le string suivant:
i='1.2.840.113747.20040531165138.3388.3000.672' de facon à avoir un nouveau string j='3000.672' ou j='3000.672'. Je ne voudrai pas considerer les chiffres d´avant.
Alors morty, si j'ai bien compris tu ne veux que la fin de ton nombre donc
Sachant qu'en Python tu peux aussi compter les chaines à l'envers (de droite à gauche) tu peux aussi faire comme ca:Code:
1
2
3 i='1.2.840.113747.20040531165138.3388.3000.672' j=i[35:] #j= la chaine 'i' du charactere 35 jusqu'à la fin
Code:
1
2
3 i='1.2.840.113747.20040531165138.3388.3000.672' j=i[-8:] #j= la chaine 'i' du charactere -8 jusqu'à la fin
Pour le problème posé, et si on a la flemme de compter jusqu'à 35:
Code:
1
2 index=j.find("3000") j=j[index:]
C’est une question de conjugaison. J’ai essayé d’être humoristique (un humour mi-figue mûre, mi-raisin vert) pour ne pas jouer au père Vaugelas. Je suis ahuri et parfois excédé de voir certaines fautes d’orthographes faites sur des points d'un usage quotidien constant.
Si le but est de récuperer les deux derniers nombres, je propose:Code:
1
2
3 i='1.2.840.113747.20040531165138.3388.3000.672' '.'.join(i.split('.')[-2:])
Je pense, et j’espère, cependant, que morty cherche une solution plus générale.
Étant réduit à conjecturer ce qu’est le cas général pour toi, morty, je suppose que tu cherches à capturer le deux derniers des groupes de nombres qui sont séparés par des points et je propose donc deux possibilités:
Code:
1
2
3 i='1.2.840.113747.20040531165138.3388.3000.672' print i[i[0:i.rfind('.')].rfind('.')+1:]
Code:
1
2
3 i='1.2.840.113747.20040531165138.3388.3000.672' print '.'.join(i.split('.')[-2:])
Merci pour toutes vos reponses...Un merci particulier à Eyquem pour son apport pythonesque et linguistique.
Une regex est sans doute le mieux
Code:
1
2
3 import re pat = re.compile('\d+?\.\d+\Z') print pat.search(i).group()
Me rappelant de la remarque suivante de Antoine935,
http://www.developpez.net/forums/d76...e/#post4427182
j'ai pensé qu’il devait être possible d’optimiser la recherche par regex en parcourant la chaîne à partir de la fin.
Bingo: ça diminue le temps de 45%.
Dans la foulée, j’ai testé les autres solutions.
Surprise: la méthode d’apparence compliquée avec rfind() est la plus rapide. Demi-surprise en fait car si j’ai pensé à cette solution c’est que je savais que les méthodes find() sont ultra véloces.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 i='1.2.840.113747.20040531165138.3388.3000.672' import re from timeit import Timer repet = 5 iterat = 1000 a = Timer("pat.search(i).group()",'from __main__ import pat,i').repeat(repet,iterat) b = Timer("i[[ x for x in xrange(len(i)) if i[x]=='.'][-2]+1:]",'from __main__ import pat,i').repeat(repet,iterat) c = Timer("patinv.match(i[::-1]).group()[::-1]",'from __main__ import patinv,i').repeat(repet,iterat) d = Timer("'.'.join(i.split('.')[-2:])",'from __main__ import pat,i').repeat(repet,iterat) e = Timer("i[i[0:i.rfind('.')].rfind('.')+1:]",'from __main__ import pat,i').repeat(repet,iterat) print "pat.search(i).group()\t\t\t",' '.join([str(u)[0:6] for u in a]) print print "i[[ positions de '.'][-2]+1:]\t\t",' '.join([str(u)[0:6] for u in b]) print print "patinv.match(i[::-1]).group()[::-1]\t",' '.join([str(u)[0:6] for u in c]) print print "'.'.join(i.split('.')[-2:])\t\t",' '.join([str(u)[0:6] for u in d]) print print "i[i[0:i.rfind('.')].rfind('.')+1:]\t",' '.join([str(u)[0:6] for u in e])
Code:
1
2
3
4
5
6
7
8
9 pat.search(i).group() 0.1168 0.1203 0.1252 0.1202 0.1200 i[[ positions de '.'][-2]+1:] 0.0681 0.0652 0.0673 0.0651 0.0694 patinv.match(i[::-1]).group()[::-1] 0.0204 0.0200 0.0231 0.0208 0.0209 '.'.join(i.split('.')[-2:]) 0.0148 0.0128 0.0128 0.0127 0.0161 i[i[0:i.rfind('.')].rfind('.')+1:] 0.0092 0.0093 0.0100 0.0092 0.0092
Tu parles. C'est vite dit.Citation:
Une regex est sans doute le mieux
J'ai pas testé mais la regex est peut être un peu plus rapide si on la compile avant, c'est intéressant seulement si on souhaite faire cette manipulation quelque dizaine ou centaine de fois je pense
C'est le cas. Je ne sais pas comment il se fait que les regex ne se trouvent pas dans le code mais les les résultats ont été obtenus avec
Ces regex sont importées dans chaque instance de Timer parCode:
1
2 pat = re.compile('\d+\.\d+\Z') patinv = re.compile('\A\d+\.\d+')
etCode:'from __main__ import pat,i'
Je pousse le souci de bien comparer jusqu'à importer une regex dans toutes les instances, même celles qui n’en ont pas besoin pour exécuter la ligne de code.Code:'from __main__ import patinv,i'
Eyquem, peux-tu me dire comment tu obtiens les temps d'éxécution de ton code ? Merci :)
Salut scheme,
Le code que j’ai mis dans le message #11 ne fonctionne pas si on le lance après l’avoir simplement copié-collé parce que, pour une raison que j’ignore, il lui manque les deux lignes qui créent les deux regex utilisées par deux des méthodes.
Il faut lui ajouter ces deux lignes, qui sont
Code:
1
2 pat = re.compile('\d+\.\d+\Z') patinv = re.compile('\A\d+\.\d+')
Soit dit en passant, quand une chaîne qui contient un point. est AFFICHÉE, le point est considéré par le bidule qui affiche (stdout ?) comme...un point. Normal.
Mais quand une chaîne qui contient . est passée à la fonction RE.COMPILE(), celle-ci saisit le point et le traduit par “n’importe quel caractère sauf \n“.
Pour signifier à re.compile() que, dans la regex qu’elle construit, elle doit coder un vrai caractère point . tout simple et uniquement ce caractère, il faut échapper le point de la chaîne par le signe \ placé devant.
Ce \ signifie un échappement au sein de re.compile(), pas dans la chaîne. Dans une chaîne, \ échappe d’autres trucs mais pas le point.
Si on met \. dans la RE passée à re.compile(), on produit les résultats voulus quand il y a uniquement un . dans i. Pour un séparateur ; ou *, ça ne marchera pas.
Alors que si on met un point simple . dans la RE, ça marchera quel que soit le séparateur.
J’ai préféré mettre \. pour n’induire personne en erreur.
NB : pour moi RE = la chaîne passée à re.compile()
Je conseille aussi d’ajouter des lignes
en copiant-collant les expressions qui sont dans les Timer( ) pour s’assurer qu’elles ne sont pas erronées et qu'elles donnent bien toutes le même résultat.Code:
1
2
3 print pat.search(i).group() print i[[ positions de '.'][-2]+1:] # etc
Merci de ta réponse Eyquem, mais en fait je cherchais plus à savoir comment otenir les temps de réponse, ce qu'il y a à droite en rose dans le message #11
Eh bien il suffit de copier-coller le code du message #11 (en y ajoutant les deux lignes manquantes) et de faire tourner....
Maintenant si tu veux comprendre ce qui se passe....
Une instance de Timer() possède deux méthodes de mesure de temps:
- timeit(iterat) qui produit un float donnant le temps en secondes du nombre d’itérations iterat
- repeat(repet , iterat) qui produit une liste de floats donnant le temps en secondes du nombre d’itérations iterat ; repet est le nombre de fois où la mesure de temps avec iterat itérations a été faite, et c’est donc le nombre de floats dans la liste résultat
Dans mon code je fais un traitement de chaîne sur les floats transformés en string par str(u) de façon à ne faire afficher que les premiers chiffres caractéristiques des floats. C’est pour l’affichage, afin que tous les floats d’une liste tiennent sur une seule liste (ça dépend aussi du nombre repet).
Merci :)