Page 1 sur 1

[R] Suppression puis ajout dans un tableau

Posté : mar. 25 mars 2014 18:41
par clark17
Bonjour à tous,

Je fais face à un petit problème dont je ne trouve pas la solution.
J'ai un petit tableau qui contient différentes variables. Je souhaite substituer une plage du tableau (entre les valeurs 03 et 1a) par une autre qui n'est pas forcément de la même taille.
le tableau de départ:
► Afficher le texte
Le tableau à insérer:
► Afficher le texte
Le tableau que je souhaite obtenir à la fin:
► Afficher le texte
Voila le code que j'ai pondu pour le moment:

Code : Tout sélectionner

#include <Array.au3>

Local $tableau[15] = [ _
        "ff", _
        "03", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "00", _
        "1a", _
        "ff"]

Local $tableau2[3] = [ _
        "03", _
        "99", _
        "1a"]

_ArrayDisplay($tableau)

Local $index_depart = _ArraySearch($tableau, "03", 0, 0)
Local $index_arrivee = _ArraySearch($tableau, "1a", 0, 0)

MsgBox(0, "Index départ", $index_depart)
MsgBox(0, "Index arrivée", $index_arrivee)

For $i=$index_depart to $index_arrivee
    _ArrayDelete($tableau, $i)
    _ArrayDisplay($tableau)
Next

_ArrayDisplay($tableau)

_ArrayReverse($tableau2)

For $i=0 to Ubound($tableau2) - 1
    _ArrayInsert($tableau, $index_depart, $tableau2[$i])
    _ArrayDisplay($tableau)
Next

_ArrayDisplay($tableau)
 
Le problème c'est qu'il ne m'efface pas les bonnes lignes et je suis perdu je ne comprend pas pourquoi...

Merci de votre aide.

Re: [..] Suppression puis ajout dans un tableau

Posté : mar. 25 mars 2014 22:35
par mikell
Explication dans le fichier d'aide :
"If the $iElement is greater than the array size then the last element is destroyed."

Démonstration :

Code : Tout sélectionner

For $i=$index_depart to $index_arrivee
    _ArrayDelete($tableau, $i)
    _ArrayDisplay($tableau, "index " & $i & " détruit !")
Next
Solution :

Code : Tout sélectionner

For $i=$index_depart to $index_arrivee
    _ArrayDelete($tableau, 1)
    _ArrayDisplay($tableau, "index 1 détruit !")
Next
Maintenant, pour moins stresser ton processeur tu peux aussi faire comme ça
► Afficher le texte

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 01:07
par clark17
mikell a écrit :Solution :

Code : Tout sélectionner

For $i=$index_depart to $index_arrivee
    _ArrayDelete($tableau, 1)
    _ArrayDisplay($tableau, "index 1 détruit !")
Next
Autant pour moi j'avais pas pensé qu'avec une boucle mon nombre de ligne se réduisait! ;-)

Maintenant pour ta solution avec les regex c'est beaucoup plus élégant c'est clair. Je viens lire quelques tuto sur les regex c'est un peu plus clair.
Par contre je bloque toujours sur un point. Si je souhaite remplacer uniquement la deuxième occurrence, comment faire?
J'ai tenté ceci:
► Afficher le texte
Mais ça ne fonctionne pas...

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 01:33
par jchd
Le facteur de répétition {2} ne fait pas ce que tu veux lui faire faire. Il équivaut à écrire ton pattern sous la forme "03.+?1a(03.+?1a)" d'un seul bloc, où seule les occurences paires de "03.+?1a" seraient capturées, donc remplacées. La chaîne sujet ne contient pas une telle séquence et elle est donc invariante par l'opération.

Ce qu'il te faut ici est différent :

Code : Tout sélectionner

$string3 = StringRegExpReplace($string1, '03.+?1a[b].+[/b](03.+?1a)', $string2, 1)
L'élément .+ en gras permet de passer outre les caractères qui se trouvent entre les séquences et, là, seule le groupe capturé sera remplacé.
Revois l'aide de la fonction et en particulier son dernier paramètre optionnel et la lumière éclairera ton visage d'un sourire de compréhension, au cas où il serait possible que le sujet contienne plus de deux fois la chaîne "03.+?1a" cherchée et que tu ne veuilles remplacer que la seconde occurence.

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 02:20
par clark17
J'avais regardé la doc et si je ne dis pas de bêtises me dernier paramètre est count. C'est le nombre d’occurrence à remplacer et non le n° de celle à remplacé ?
Dans mon exemple c'est bien seulement la deuxième occurrence que je cherche à remplacer. Par conséquent si je fais:

Code : Tout sélectionner

$string3 = StringRegExpReplace($string1, '(03.+?1a)', $string2, 2 )
 
cela me remplace les deux premières et pas seulement la deuxième...

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 08:49
par jchd
Correct, mais ça n'a rien à voir avec la question que tu posais. Par principe, j'évite de répondre aux questions pas encore posées :mrgreen:

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 09:30
par mikell
jchd si j'ai bien compris le but est à partir de cette chaine :
"ff,03,00,00,00,00,00,00,00,00,00,00,09,1a,ff,ff,03,00,00,00,00,00,00,00,00,00,00,00,1a,ff"
obtenir :
"ff,03,00,00,00,00,00,00,00,00,00,00,09,1a,ff,ff,03,99,1a,ff"
or ton expression

Code : Tout sélectionner

$string3 = StringRegExpReplace($string1, '03.+?1a.+(03.+?1a)', $string2, 1)
retourne "ff,03,99,1a,ff"

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 09:43
par jchd
Oops, pas collé le bon clip :

Code : Tout sélectionner

$string3 = StringRegExpReplace($string1, '03.+?1a.+\K(03.+?1a)', $string2, 1)

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 11:17
par clark17
En fait, ce que je cherche à faire c'est une fonction qui me remplace une chaine de caractère par une autre en spécifiant une occurrence précise.
Par exemple transformer:

Code : Tout sélectionner

03mot11a03mot21a03mot31a
En:

Code : Tout sélectionner

03mot11a03motmodifié03mot31a
En spécifiant l'occurrence n°2 dans ce cas.

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 15:44
par mikell
Attention quand tu parles d'occurences, en fait tu parles de plusieurs chaines identiques où tu veux remplacer la 2ème et pas les autres (par exemple)
"mot1" c'est pas la même chose que "mot2"

Code : Tout sélectionner

$string = "03MOT11a03MOT11a03MOT11a"
Msgbox(0,"",  _StringReplaceOcc($string, "MOT1", "tralala", 2) )

Func _StringReplaceOcc($string, $out, $in, $occur)
  Return StringRegExpReplace ($string, '(?:.*?\K' & $out & '){' & $occur & '}' , $in )  
EndFunc
Maintenant ça peut aussi être des chaines différentes mais correspondant au même motif (pattern...) de regex : "MOT1", "MOT2" etc

Code : Tout sélectionner

$string2 = "03MOT11a03MOT21a03MOT31a"
Msgbox(0,"",  _StringReplaceOcc2($string2, '(MOT\d)', "tralala", 2) )

Func _StringReplaceOcc2($string, $pattern, $in, $occur)
  $var = StringRegExpReplace ($string, '(?:.*?' &$pattern& '){' &$occur& '}.*' , '$1' )
  Return StringReplace ($string, $var, $in )  
EndFunc

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 16:24
par clark17
mikell a écrit :Maintenant ça peut aussi être des chaines différentes mais correspondant au même motif (pattern...) de regex : "MOT1", "MOT2" etc

Code : Tout sélectionner

$string2 = "03MOT11a03MOT21a03MOT31a"
Msgbox(0,"",  _StringReplaceOcc2($string2, '(MOT\d)', "tralala", 2) )

Func _StringReplaceOcc2($string, $pattern, $in, $occur)
  $var = StringRegExpReplace ($string, '(?:.*?' &$pattern& '){' &$occur& '}.*' , '$1' )
  Return StringReplace ($string, $var, $in )  
EndFunc
C'est bien ça que je cherchais à faire! Je me suis effectivement mal exprimé sur les chaines différentes et non occurrences.
Maintenant j'essaye de comprendre la regex et là j'ai du mal.

La première ( ) c'est pour capturer le morceau.
Le ?: c'est pour lui dire de ne pas être gourmand et s'arrêter sur le premier 1a qu'il trouve?
Le .* c'est pour définir n'importe quels caractères.
Par contre le deuxième ? Je ne comprends pas son utilité?
Les {} pour définir sur quelle chaine il s’arrête.
Enfin le $1 qui correspond à ce qu'il trouve entre les parenthèses c'est ça?

Ensuite avec StringReplace tu changes ce que tu as trouvé avec la Regex.

Désolé pour ces questions, mais les regex me font mal à la tête!

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 16:53
par mikell
?: c'est pour indiquer un groupe non-capturant (ne pas référencer le contenu)
.*? veut dire : n'importe quel caractère, 0 ou plusieurs fois, non-gourmand

Si on remplace les variables par des valeurs, le regex donne :

Code : Tout sélectionner

$var = StringRegExpReplace ($string2, '(?:.*?(MOT\d)){2}.*' , '$1' )
Ce qui est capturé et retourné par $1 est le groupe entre parenthèses
Donc là c'est le 2ème groupe (MOT\d) rencontré qui est référencé
Note que ça peut aussi s'écrire

Code : Tout sélectionner

$var = StringRegExpReplace ($string2, '(?:.*?(MOT\d))(?:.*?(MOT\d)).*' , '$2' )
Là on met $2 parce que dans l'expression figurent 2 groupes capturants

Code : Tout sélectionner

$string2 = "03MOT11a03MOT21a03MOT31a"

$var = StringRegExpReplace ($string2, '(?:.*?(MOT\d)){2}.*' , '$1' )
; $var = StringRegExpReplace ($string2, '(?:.*?(MOT\d))(?:.*?(MOT\d)).*' , '$2' )

$res = StringReplace ($string2, $var, "tralala")
Msgbox(0,"", "départ : " & $string2 &@crlf& "capture : " & $var &@crlf& "replace : " & $res)

Re: [..] Suppression puis ajout dans un tableau

Posté : jeu. 27 mars 2014 17:40
par clark17
Super merci je comprends mieux!