parsing | |
neoreb | 12-Feb-2007/17:55:07+1:00 |
bonjour la ligne suivante me permet de sauvegarder les indexes des occurences de la chaine "wor". parse string [any [to "wor" mark: (append tableau index? mark) 3 skip] to end] Ce que je voudrais est plus compliqué. Je souhaiterais sauvergarder dans un tableau les indexes de tous les triplets rencontrés dans string. Exemple: Si string: "word world" je voudrais obtenir dans tableau à la fin du parsing un truc du style: wor 1 6 ord 2 rdw 3 dwo 4 orl 7 rld 8 J'ai bien pensé à une solution avec trois boucles repeat count 26 imbriquées mais je me doute qu'on doit pouvoir faire mieux... merci | |
guest2 | 12-Feb-2007/19:00:11+1:00 |
humm? à mon avis ça vaut pas le coup de faire un parser pour ça. une boucle while est tout aussi bien vu que tu traites chaque caractère de la chaine. A la limite c'est intéressant de parser si tu veux éliminer certains caractères comme la ponctuation. Première version, avec une règle (dico) qui se modifie au fur et à mesure. Aucun intérêt et puis c'est plus dûr à comprendre pour un débutant. string: {this is the world word world !} triplet: "" dico: ["vide"] statistique: [] letters: charset [#"a" - #"z"] parse/all string [ any [ pos: [ copy triplet dico ( append select statistique triplet index? pos pos: next pos ) | copy triplet [3 letters] ( append dico reduce ['| triplet] append statistique reduce [triplet cp []] ) ] :pos | skip ] ] probe statistique la seconde version est plus lisible et surement plus rapide, encore que... string: {this is the world word world !} triplet: "" statistique: [] letters: charset [#"a" - #"z"] parse/all string [ any [ pos: copy triplet [3 letters] ( unless all [ stats: select/skip statistique triplet 2 block? stats/1 ][ stats: next reduce [triplet cp []] append statistique head stats ] append stats/1 index? pos pos: next pos ) :pos | skip ] ] probe statistique | |
guest2 | 12-Feb-2007/19:31:15+1:00 |
hum je viens de me rendre que c'est pas exactement ce que tu fais dans ton exemple. en fait, tu tiens pas compte des espaces, tu fais comme si tout était collé. hum... t'es sûr que c'est ça que tu veux faire ? je comprends pas bien le but... mais je pense qu'il suffit de modifier le charset de mes exemples et rajouter l'espace pour que ça marche: letters: charset ["#a"-#"z" " "] | |
guest2 | 12-Feb-2007/19:37:53+1:00 |
ferais mieux de tester avant de poster: rien à voir avec le charset, il faut juste virer l'option '/All' de la commande parse, et faire un trim sur la variable triplet pour virer les espaces. source corrigé: string: {this is the world word world !} triplet: "" statistique: [] letters: charset [#"a" - #"z"] parse string [ any [ pos: copy triplet [3 letters] ( triplet: trim/all triplet unless all [ stats: select/skip statistique triplet 2 block? stats/1 ][ stats: next reduce [triplet cp []] append statistique head stats ] append stats/1 index? pos pos: next pos ) :pos | skip ] ] probe statistique Bon, c'est pas tout ça, mais la pause déjeuner est finie et j'ai du boulot... | |
neoreb | 12-Feb-2007/21:17:42+1:00 |
Effectivement, avec une boucle while on s'en sort tres bien:trim/with string ".,' " while [not tail? string] [triplet: copy/part string 3 if (length? triplet) = 3 [if error? try [append select tableau triplet index? string] [append tableau reduce [triplet reduce [index? string]]] ] string: next string ] ton code m'a appris pas mal de choses sur parse merci | |
guest2 | 12-Feb-2007/21:54:03+1:00 |
hmm... je pensais que tu avais besoin de la position des triplets caractères spéciaux inclus. Effectivement, sans c'est plus simple. En elliminant systématiquement les 4 dernières entrées de ton tableau, tu évites le test sur la longueur. Mais bon, c'est de l'optimisation j'aime bien ton idée de gérer l'erreur plutôt que tester l'existence dans le tableau, par contre je sais pas si c'est très performant. string: {this is the world word world !} tableau: [] trim/with string ".,' !" forall string [ triplet: copy/part string 3 any [ attempt [append select tableau triplet index? string] append tableau reduce [triplet reduce [index? string]] ] ] clear skip tail tableau -4 probe tableau | |
neoreb | 12-Feb-2007/22:08:24+1:00 |
ah oui c'est joli le any et le attempt. Pas encore trop l'habitude d'utiliser ces fonctions qui n'existent pas dans les langages classiques. | |
guest2 | 12-Feb-2007/22:18:13+1:00 |
tient en parlant de performance. N'utilise surtout pas le forall (même si ça donne un code plus concis) comme je l'ai fait mais plutôt le while comme tu l'as fait. Et n'oublie pas que la boucle la plus rapide est 'until (j'ai fait des tests) au lieu d'écrire: while [not tail? string][ ... string: next string ] tu peux écrire: until [ ... not tail? string: next string ] le gain est infime, mais sur des millions d'occurences, ça peut compter. Ces 2 structures ne sont pas totalement équivalantes (vu que tu entres au moins une fois dans le 'until même si string est vide) mais dans la majorité des usages un 'while est transposable en 'until | |
guest2 | 12-Feb-2007/22:32:26+1:00 |
hum hum , je sais pas ce que j'ai aujourd'hui mais je bavarde, je bavarde... enfin, en terme d'optimisations y'a plus urgent que le problème du until. - vérifier que le attempt (ou ton if error? try) n'est pas plus lent qu'un test sur le select. - replacer les append, par des insert tail - si ton tableau grossit trop, il faut prévoir de le transformer en list! ou même en hash! pour accélérer le select. - et puis t'as aussi intérêt à prè-allouer de la mémoire (fonction make) pour ton tableau , comme ça, les insert sont plus rapides. Je sais, t'as rien demandé mais il fallait que quelq'un le dise, non-de-diou ! | |
neoreb | 13-Feb-2007/9:29:52+1:00 |
bein merci pour toutes ces infos. Tout ça c'est bon à savoir Tiens j'ai une autre question: Dans certains scripts je vois assez souvent une initialisation du style: bloc: copy [] je reutilise ça betement mais je n'arrive pas à voir la différence avec: bloc: [] Par contre j'ai bien compris la difference entre bloc2: bloc et bloc2: copy bloc | |
Didec | 13-Feb-2007/11:40:59+1:00 |
Généralement, ça dépend si l'instruction est dans une fonction (susceptible donc d'être appelé plusieurs fois) ou dans le déroulement du script (genre déclaration d'une variable "globale" au départ). Dans le premier cas (avec 'copy), cela permet d'avoir un nouveau bloc vide à chaque fois. Dans le deuxième cas, ça réutilise le même bloc et donc ce qu'il contient éventuellement : f1: func [v /local b] [b: [] append b v probe b] f2: func [v /local b] [b: copy [] append b v probe b] r11: f1 'a r12: f1 'b r13: f1 'c same? head r11 head r12 r21: f2 'a r22: f2 'b r23: f2 'c same? head r21 head r22 | |
guest2 | 13-Feb-2007/13:04:01+1:00 |
yeah, j''ai rien compris à ton explication Didec personnellement, j'aime bien utiliser a: clear [] plutôt que a: cp [] Comme ça, Rebol a moins de trucs à recycler. | |
Didec | 13-Feb-2007/15:20:32+1:00 |
Bonne idée, mais :f1: func [v /local b] [b: [] append b v probe b] f2: func [v /local b] [b: copy [] append b v probe b] f3: func [v /local b] [b: clear [] append b v probe b] r11: f1 'a r12: f1 'b r13: f1 'c print remold [r11 r12 r13] same? head r11 head r12 r21: f2 'a r22: f2 'b r23: f2 'c print remold [r21 r22 r23] same? head r21 head r22 r31: f3 'a r32: f3 'b r33: f3 'c print remold [r31 r32 r33] same? head r31 head r32 En regardant bien les résultats, selon le principe utilisé pour initialier 'b dans chaque fonction, on voit que les résultats sont différents. La règle, c'est qu'il n'y en a pas ! Il faut utiliser le bon principe au bon moment, selon ses besoins. J'ai constaté souvent, l'utilisation inutile de 'copy dans beaucoup de scritps. Mais ce n'est pas vraiment génant. Il vaut mieux un 'copy de trop qu'un de moins | |
neoreb | 13-Feb-2007/21:58:19+1:00 |
ok vu. c'est un peu bizarre comme fonctionnement mais bon suffit de le savoir. merci | |
Login required to Post. |