[R] StringSplit et conditionnelle

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
Ric
Niveau 1
Niveau 1
Messages : 9
Enregistré le : ven. 15 août 2014 20:04
Status : Hors ligne

[R] StringSplit et conditionnelle

#1

Message par Ric »

Bonsoir à tous :)

Je ne savais pas trop comment titrer, il n'est peut-être pas très adapté.

J'étais venu il y a quelques temps demander conseil pour m'orienter sur une méthodologie adaptée à ma problématique, dans ce sujet du forum. J'étais donc parti sur la première suggestion, de jguinch, à savoir chacune des lignes de mon fichier CSV est lue (FileReadLine, StringSplit), ignorée ou non, agrémentée d'informations complémentaires, puis écrite ou pas dans un nouveau fichier. L'ensemble est fonctionnel, pas de gros soucis.

En ce moment j'essaie de rajouter une fonctionnalité 'cosmétique', permettant d'affiner le tri déterminant si une ligne du CSV doit être ignorée ou non avant la réécriture dans le CSV de sortie, mais je coince un peu.

Je m'explique. Dans le fichier source CSV d'exemple, précédemment inséré (disponible ici), vous pouvez observer que les colonnes 24 à 48 comporte des OUI et des NON. Certaines de ces colonnes sont complétement ignorées, d'autres pas, et dans ce cas sont filtrées en fonction de la réponse. Mon script fonctionnel, sur la méthode proposée par lecture ligne à ligne, éclatement en tableau, vérification de conditions, et réécriture dans un fichier de sortie, roule bien. Exemple ci dessous anonymisé (on ne se moque pas :p ) :
► Afficher le texte
Ainsi, les OUI sur certaines colonnes m'intéressant, dès qu'il y en a 1, je conserve la ligne (ce qui dans la fonction est traduit par si je n'ai que des NON sur les colonnes qui m'intéressent -d'où tous les AND- j'ignore et je passe à la ligne suivante). Jusque là tout va bien, tant que les 'filtres' sont ainsi définis et ne bougent pas :)

J'aimerai rajouter une fonctionnalité de 'filtre' personnalisable. Via un ensemble de Checkbox, je permettrai à l'utilisateur de sélectionner les filtres sur lesquels il souhaite se concentrer. L'état de chacune des checkbox, défini en amont, est stocké en variables. L'utilisateur sélectionnerait par exemple le filtre (colonne) 24 et 26 ; ce qui indiquerait que seules les lignes comportant -indifféremment- un oui dans une de ces colonnes serait à conserver.

Je récupère bien mes variables conditionnelles, via une petite GUI comportant les Checkbox, mais je coince pour implémenter cette conditionnelle dans la boucle ligne par ligne de l'exemple de code inséré ci-dessus. Sur deux valeurs conditionnelles, je pourrai l'écrire ainsi

Code : Tout sélectionner

If $aSplit[24] = "Non" OR $aSplit[26] = "Non" Then ContinueLoop
Mais sur un ensemble de 11 conditions, je coince, il y aurait trop de combinaisons pour tout écrire manuellement.

Si je définis le OUI/NON via une lecture de la variable de la check, pour obtenir une commande de cet ordre :

Code : Tout sélectionner

 If $aSplit[25] = $valCol25 AND $aSplit[26] = $valCol26 AND $aSplit[27] = $valCol27 AND $aSplit[28] etc. Then ContinueLoop
Mon AND devient trop discriminant : seule l'ensemble des lignes répondant strictement aux critères sera retourné, or il y aura de nouvelles colonnes de fait à ignorer, quelle que soit leur état. Si j'enchaine les OR, je vais intégrer malgré les conditions des lignes qui ne m'intéressent pas.

Idéalement, il faudrait que pour les colonnes sélectionnées par l'utilisateur (via le filtre checkbox), ma succession de AND soit modulable. Ainsi, par défaut ma commande générique est toujours la suivante :

Code : Tout sélectionner

If $aSplit[25] = "Non" AND $aSplit[26] = "Non" AND $aSplit[27] = "Non" _
        AND $aSplit[28] = "Non" AND $aSplit[29] = "Non" AND $aSplit[30] = "Non" _
        AND $aSplit[31] = "Non" AND $aSplit[32] = "Non" AND $aSplit[33] = "Non" _
        AND $aSplit[34] = "Non" AND $aSplit[35] = "Non" Then ContinueLoop
Mais si l'utilisateur active son filtre sur les colonnes (par exemple) 27, 28 et 29, la commande serait amputée des champs dédiés pour ne finalement conserver que ceux-ci (toujours dans la logique si la valeur est NON dans les colonnes qui m'intéressent, j'ignore la ligne)

Code : Tout sélectionner

If $aSplit[27] = "Non" AND $aSplit[28] = "Non" AND $aSplit[29] = "Non" Then ContinueLoop
J'avais imagé peut-être aussi de pouvoir conserver la commande et mes AND, via une variable qui lit l'état des check, mais qui dans l'éventualité où une n'est pas actionnée, ne chercherait pas une valeur mais viendrait s'assurer juste que la colonne n'est pas vide (ce qui me permettrait de conserver peut-être la commande complète). Dans mon exemple, où 27,28 et 29 seraient filtrés, cela deviendrait quelque chose comme ceci :

Code : Tout sélectionner

If $aSplit[25] = $valCol25 AND $aSplit[26] = $valCol26 AND $aSplit[27] = $valCol27 _
        AND $aSplit[28] = $valCol28 AND $aSplit[29] = $valCol29 AND $aSplit[30] = $valCol30 _
        AND $aSplit[31] = $valCol31 AND $aSplit[32] = $valCol32 AND $aSplit[33] = $valCol33 _
        AND $aSplit[34] = $valCol34 AND $aSplit[35] = $valCol35 Then ContinueLoop
Où $valCol27, $valCol28 et $valCol29 = "Non" après lecture des check et où tous les autres seraient un $valColxx = "champ texte indiscriminé" . <- mais peut-on trouver un filouterie pour écrire quelque chose comme cela, genre un wildcard générique indiquant n'importe quel type de texte, que je pourrai faire passer en variable ?

J'imagine que je n'ai pas été démonstratif dans mon souci, je le sens :mrgreen:
C'est surtout une méthodologie/logique que je viens solliciter, pas un script tout fait, ne vous ennuyez pas si vous avez une idée :)
Peut-être faudrait-il que je retourne la logique ; au lien d'ignorer la ligne qui a des valeurs qui ne m'intéressent pas dans certaines colonnes, me concentrer uniquement sur celles qui ont des valeurs qui m'intéressent. Mais c'est alors toute la structure du script qu'il me faudrait revoir, et je pense que cette fonction 'cosmétique' ne sera pas proposée.
Modifié en dernier par Ric le sam. 30 août 2014 22:26, modifié 1 fois.
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#2

Message par mikell »

Il me semble qu'inverser le pb et valider en utilisant un booléen pourrait être une bonne idée
Après tout

Code : Tout sélectionner

If $aSplit[25] = "Non" AND $aSplit[26] = "Non" AND $aSplit[27] = "Non" _
        AND $aSplit[28] = "Non" AND $aSplit[29] = "Non" AND $aSplit[30] = "Non" _
        AND $aSplit[31] = "Non" AND $aSplit[32] = "Non" AND $aSplit[33] = "Non" _
        AND $aSplit[34] = "Non" AND $aSplit[35] = "Non" Then ContinueLoop
C'est la même chose que ça

Code : Tout sélectionner

$test = 0
For $i = 25 to 35
   If $aSplit[$i] <> "Non" Then $test = 1
Next
If $test = 0 Then ContinueLoop
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Avatar du membre
jguinch
Modérateur
Modérateur
Messages : 2515
Enregistré le : lun. 14 févr. 2011 22:12
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#3

Message par jguinch »

Je pense avoir compris ton (long) énoncé.
Il faut, comme Mikell l'a indiqué, utiliser une boucle de 24 à 48 (colonnes concernées par le oui/non apparemment).
Ensuite, pour le côté personnalisable, tu peux simplement mettre les numéros des colonnes à vérifier dans une variable (tableau ou chaine) et vérifier pour chaque colonne "non", si le numéro (de la colonne) est contenu dans cette variable :
► Afficher le texte
Le script, ça fait gagner beaucoup de temps... à condition d'en avoir beaucoup devant soi !
Faco
Niveau 4
Niveau 4
Messages : 80
Enregistré le : lun. 29 juil. 2013 18:09
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#4

Message par Faco »

Avec le bout de code de Mikell :
► Afficher le texte
Ric
Niveau 1
Niveau 1
Messages : 9
Enregistré le : ven. 15 août 2014 20:04
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#5

Message par Ric »

Bonsoir,

Merci du coup d’œil et de la suggestion.

Je ne pourrai m'y remettre que ce week-end, mais merci en tous les cas.
Ric
Niveau 1
Niveau 1
Messages : 9
Enregistré le : ven. 15 août 2014 20:04
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#6

Message par Ric »

Bonsoir,

Enfin en week-end, et j'ai pu prendre le temps de m'y repencher. J'ai regardé les éléments que vous m'avez suggérés, et j'ai commencé à voir ce que je pouvais réaliser.

Je suis parti surtout sur la boucle de jguinch, l'état des checkbox déterminant la valeur de $sFilter. C'est la méthode avec laquelle j'ai fait le plus d'essais, et j'ai essayé de m'approprier StringInStr.

Cette méthode et les autres suggestions me posent un souci, je m'y suis peut-être mal pris, mais il me semble que le filtre opéré est discriminant. Dans la suggestion de jguinch :

Code : Tout sélectionner

If $aSplit[$i] = "Non" AND StringInStr(";" & $sFilter & ";", ";" & $i & ";") Then
Ainsi, par défaut disons que je souhaite me concentrer sur les colonnes 27 à 31 et 33 à 35, les checkbox retournent un $sFilter = "27;28;29;30;31;33;34;35". La finalité étant de conserver les lignes possédant au moins un "Oui" dans les colonnes ainsi filtrées (et dans la logique du script d'ignorer donc celles qui contiennent un "Non' dans toutes ces colonnes à la fois). La fonctionnalité ainsi écrite exclut la ligne dès qu'un "Non" est détecté dans l'une des colonnes passées en filtre, par ordre de consultation, basculant $iWrite à 0.

Concrètement, je n'obtiendrai ici que les lignes ayant un "Oui' dans les 8 colonnes à la fois.

Je me suis peut-être emmêlé les pinceaux entre les ContinueLoop et les ExitLoop. :/ Je n'ai peut-être pas compris l'utilisation de StringInStr ? Ou alors j'ai mal compris les suggestions proposées ? Les autres méthodes me semblent aussi discriminantes, bien que je ne les ai pas travaillées.
Avatar du membre
jguinch
Modérateur
Modérateur
Messages : 2515
Enregistré le : lun. 14 févr. 2011 22:12
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#7

Message par jguinch »

Ah, j'avais compris qu'il fallait ignorer les lignes qui avaient au moins un "non" dans les colonnes filtrées...
Du coup, j'ai édité mon code, dis-moi si c'est OK.
Le script, ça fait gagner beaucoup de temps... à condition d'en avoir beaucoup devant soi !
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#8

Message par mikell »

Ric a écrit :La finalité étant de conserver les lignes possédant au moins un "Oui" dans les colonnes ainsi filtrées
C'est une simple histoire de logique, pour faire simple :

Code : Tout sélectionner

$ongarde = false        ; initialise la variable
For $i = 27 to 35
   If $i <> 32 Then   ; ce test ne concerne pas la col 32
      If $aSplit[$i] <> "Non" Then $ongarde = true      ; bascule la variable si "oui" trouvé
  EndIf
Next
If $ongarde = false Then ContinueLoop     ; on garde pas
Dans ce cas, au 1er "oui" trouvé la variable est mise à "true", le ContinueLoop ne s'applique pas et le code continue, si "false" la ligne est ignorée et on repart au début de la boucle d'analyse des lignes
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Ric
Niveau 1
Niveau 1
Messages : 9
Enregistré le : ven. 15 août 2014 20:04
Status : Hors ligne

Re: [..] StringSplit et conditionnelle

#9

Message par Ric »

C'est une simple histoire de logique
Oui, mais je me fais des nœuds parfois ^^ C'est la logique du script qui est particulière.

Le script lit un CSV source ligne par ligne, ignore si la ligne est non concluante, conserve la ligne si elle l'est. Quand il a fini de traiter ligne par ligne, il écrit alors dans le fichier de sortie suivant un canevas détaillé et en rajoutant des informations tierces quelques unes des informations des lignes validées. Ce qui fait que quand je veux conserver et obtenir certaines lignes, je dois écrire comment les ignorer en amont. Mais cela me permet d'éviter d'avoir à éditer le fichier source, d'en supprimer des lignes ou des colonnes, voire de les réagencer.

Ta suggestion me paraît simple en effet. Ma difficulté est que la plage $i est définie par 11 checkbox, qui retournent potentiellement 11 numéros de colonne. La plage est donc très variable, et peut être fragmentée. 25 à 30 et 32 à 33 et 35 par exemple. Comme elle ne peut finalement contenir qu'une colonne (28) ou les 11 à la fois.
En l'état mes checkbox que j'avais préparé pour le $sFilter de jguinch retournent une valeur xx;xx;xx;xx;xx pour les colonnes sélectionnées. Exemple sur la logique précédente $sFilter = 25;26;27;28;29;30;32;33;35

La difficulté que je vois avec le script que tu proposerais serais d'adapter la plage $i à ma plage fragmentée obtenue par les checkbox.

---

Code : Tout sélectionner

If $aSplit[$i] = "Oui" AND StringInStr(";" & $sFilter & ";", ";" & $i & ";") Then
Je m'en veux de ne pas y avoir simplement pensé, suite à la dernière suggestion de jguinch. Obnubilé par mes filouteries, je n'ai même pas simplement pensé à renverser la logique et partir sur le "Oui" à la place du "Non" dans le StringInStr... Avec l'idée que dès qu'il y en a un de trouvé, le 'marquant de conservation' est activé. Cela semble fonctionner parfaitement à présent, il n'y a plus de discrimination comme je l'avais constaté et les résultats retournés semblent cohérents. Je vais faire quelques tests complémentaires, mais cela me semble impeccable :)

Merci à tous les deux d'avoir pris le temps de jeter un œil et de déchiffrer mes explications et interrogations qui ne sont certainement pas si claires que je peux le croire :mrgreen: Encore merci, je passe en résolu ce sujet.
Répondre