Extraire des chiffres dans une chaine
Didier2-Oct-2008/21:17:43+2:00
Bonjour à vous,

Je cherche un moyen simple pour extraire uniquement les chiffres dans une chaines !
par exemple :
extraire : 12345 de 12DF34jr5

Merci d'avance,

Didier
Philippe3-Oct-2008/8:53:52+2:00
Salut,

Tout dépend de ce que tu entends par extraire : récupérer les chiffres ou ne garder que les lettres ?

extraire: "12345 de 12DF34jr5"
trim/with extraire "0123456789"
== " de DFjr"


===Philippe
Didec3-Oct-2008/9:44:34+2:00
parse is your friend, always !

chaine: "12DF34jr5"  ; chaine à filtrer
que-chiffres: ""     ; resultat

chiffre: charset "0123456789"
parse/all chaine [any [p: chiffre (append que-chiffres p/1) | skip]]

probe que-chiffres
Didec6-Oct-2008/12:10:07+2:00
J'y reviens !
comme toujours en programmation, il y a plusieurs façon de faire les choses. Le choix va dépendre de son besoin principal : compréhension, élégance, vitesse...

Voici trois versions différentes qui produisent le résultat demandé. Attention, parfois c'est la chaine source qui est modifiée, parfois pas !
Ici, je démontre la vitesse, pour l'élégance ou la compréhension, chacun jugera !
chaine: "12DF34jr5"  ; chaine à filtres

chiffre: charset "0123456789"
pas-chiffre: complement charset "0123456789"

t: now/time/precise
loop 100000 [
	chaine: copy "12DF34jr5"  ; l'original est modifié, donc on copy
	remove-each p chaine [find pas-chiffre p]
]
print ["remove-each   :" now/time/precise - t]

t: now/time/precise
loop 100000 [
	que-chiffres: copy ""  ; resultat dans une autre chaine
	parse/all chaine [any [p: chiffre (append que-chiffres p/1) | skip]]
]
print ["parse extrait :" now/time/precise - t]

t: now/time/precise
loop 100000 [
	chaine: copy "12DF34jr5"  ; l'original est modifié, donc on copy
	parse/all chaine [any [chiffre | end break | p: (remove p)]]
]
print ["parse remove  :" now/time/precise - t]
guest26-Oct-2008/16:06:29+2:00
La solution avec append semble être la plus lente.
Mais en fait on peut largement l'optimiser et elle devient alors 2 fois plus rapide que les autres.

t: now/time/precise
loop 100000 [
	que-chiffres: clear ""  ; resultat dans une autre chaine
	parse/all chaine [any [copy p some chiffre (insert tail que-chiffres p) | some pas-chiffre]]
]
print ["parse extrait :" now/time/precise - t]


il y a 2 améliorations importantes par rapport au code de Didec.
- Eviter les
ma-variable: copy ""
quand on peut reutiliser la même variable de travail dans une boucle. Préferer alors
ma-variable: clear ""
.
Ceci évite à Rebol de réallouer de la mémoire quand ce n'est pas nécessaire.
- Le parseur a été modifié pour pouvoir traiter plusieurs caractères en même temps plutôt qu'un seul caractère à la fois.

D'une façon générale, Plus la chaine ou le block à traiter en entrée est grand et plus faire des removes devient lent par rapport à des append.
Mais c'est vrai que l'utilisation de remove permet souvent d'être plus concis à l'écriture du code.
didier13-Oct-2008/22:25+2:00
C'est parfait
Merci
guest314-Oct-2008/13:36:52+2:00
intersect "612DF34jr5" "1234567890"
Didec14-Oct-2008/16:04:06+2:00
Bonne idée, mais ça ne marche pas si un chiffre est en double ou plus !!
>> intersect "612DF34jr5f6f2112fs011s2df111f20549897d4f" "1234567890"
== "6123450987"
Philippe14-Oct-2008/22:18:41+2:00
Salut,

D'ailleurs, c'est dommage qu'il n'y ait pas un équivalent de :
alpha: charset [#"A" - #"Z" #"a" - #"z"]
== make bitset! #{
0000000000000000FEFFFF07FEFFFF0700000000000000000000000000000000
}


avec une fonction intégrée à Rebol pour avoir quelque chose cela en string! :
liste-alpha: set-of-chars [#"A" - #"Z" #"a" - #"z"]
=={ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz}



===Philippe
Didec15-Oct-2008/10:14:16+2:00
C'est pas bien compliqué à faire. Inutile de le mettre en natif :
set-of-chars: func [spec [block!] /local out f s generate] [
	out: copy ""
	generate: func [b e /local sw] [
		b: to-integer b
		e: to-integer e
		if b > e [sw: b b: e e: sw]
		for i b e 1 [insert tail out to-char i]
	]
	parse spec [any [set f char! '- set s char! (generate f s) | set f char! (insert tail out f)]]
	out
]

set-of-chars [#"A" - #"Z" #"a" - #"z"]
DocKimbel15-Oct-2008/23:16:35+2:00
Y'a plus simple :

set-of-chars: func [data [block!] /local out][
	out: make string! 255
	data: charset data
	repeat c 255 [if find data c [append out to char! c]]
	out
]

set-of-chars [#"A" - #"Z" #"a" - #"z"]
== {ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz}


Philippe16-Oct-2008/6:31:01+2:00
Que j'aime cette douce émulation !



===Philippe
PS. Ce serait peut-être bien de mettre ces exemples sur la Library ?
Didec16-Oct-2008/13:26:54+2:00
Moi aussi j'aime cette émulation, c'est clair !

Je suis pas trop mauvais en Rebol, mais Doc est un Guru !!

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2