[R] Supprimer une ligne d'un array en boucle

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
eric
Niveau 5
Niveau 5
Messages : 177
Enregistré le : sam. 21 mars 2009 17:57
Localisation : Bretagne
Status : Hors ligne

[R] Supprimer une ligne d'un array en boucle

#1

Message par eric »

Bonjour,

Je souhaite chercher certaines ligne d'un array et les supprimer en boucle.

Voici un exemple de code :

Code : Tout sélectionner

#Include <Array.au3>

Local $Array[14] = [1000, 32, 200, 1000, 44 , 400, 1000, 65 , 60, 700, 1000, 72, 90 , 80]

$cherche = _ArrayFindAll($Array, 1000)


for $i=0 to UBound($cherche)-1
    
    _ArrayDelete($Array,$cherche[$i])
    _ArrayDelete($Array,$cherche[$i]+1)
            
Next

_ArrayDisplay($Array)
Le but est de cherche si 1000 est présent.
Dans ce cas supprimer la ligne 1000 ainsi que celle qui suit.

Seulement voila quand je réalise un _ArrayDelete l'array change à chaque fois et du coup je ne supprime pas les bonnes lignes.

Comment pourrais je réaliser cela tout en restant avec un array.

Merci
Modifié en dernier par ani le mar. 07 avr. 2009 12:21, modifié 1 fois.
Raison : Modification de la balise [..] du titre en [R]
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11816
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#2

Message par Tlem »

Voilà une solution comme une autre :

Code : Tout sélectionner

#Include <Array.au3>

Local $Array[14] = [1000, 32, 200, 1000, 44 , 400, 1000, 65 , 60, 700, 1000, 72, 90 , 80]
Local $Str

 For $i = 0 to UBound($Array)-1
     
    If $Array[$i] = 1000 Then
        $i+= 2
        If $i > UBound($Array) Then ExitLoop
    EndIf
    
    $Str &= $Array[$i] & ";"
Next

$Str = StringTrimRight($str, 1) ; Pour enlever le dernier point virgule.

$Array = StringSplit($str, ";")

_ArrayDisplay($Array)
Le #Include <Array.au3> n'est nécessaire que pour l'affichage du tableau, sinon, on peut s'en passer.
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
ani
Niveau 11
Niveau 11
Messages : 1826
Enregistré le : lun. 23 juil. 2007 12:31
Localisation : Bureau
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#3

Message par ani »

Bonjour :)

Code : Tout sélectionner

#Include <Array.au3>

Local $Array[14] = [1000, 32, 200, 1000, 44 , 400, 1000, 65 , 60, 700, 1000, 72, 90 , 80]

$cherche = _ArrayFindAll($aArray, $sRecherche)
_ArrayDisplay($Array)

for $i=0 to UBound($cherche)-1
    _ArrayDelete($aArray,_ArraySearch($aArray,$sRecherche))      
    _ArrayDelete($aArray,_ArraySearch($aArray,$sRecherche)+1)      
Next_ArrayDisplay($Array)

_ArrayDisplay($Array)

Exit
Voilà voilà
bonne continuation ;)
GaRydelaMer
Niveau 7
Niveau 7
Messages : 450
Enregistré le : mer. 18 mars 2009 22:12
Localisation : Montpellier
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#4

Message par GaRydelaMer »

Bonsoir

je trouve pas trés performant la solution avec _ArraySearch(), pourquoi ?

Simplement que cette fonction va également parcourir le tableau.

Donc à chaque tour de la 1er boucle la fonction va encore faire une boucle pour parcourir le tableau pour faire la recherche et renvoyer l'index.

Code : Tout sélectionner

#include <Array.au3>

Local $Array[14] = [1000, 32, 200, 1000, 44, 400, 1000, 65, 60, 700, 1000, 72, 90, 80]

$cherche = _ArrayFindAll($Array, 1000)
_ArrayReverse($cherche)
_ArrayDisplay($cherche)

For $i = 0 To UBound($cherche) - 1
    _ArrayDelete($Array, $cherche[$i] + 1)
    _ArrayDelete($Array, $cherche[$i])
Next
_ArrayDisplay($Array)
Alors la çà marche, je recherche tout les index du tableau dont la valeur est 1000
je met le tableau a l'envers pour commencer a virer de la fin du tableau vers le début, sinon les index du tableau sont renuméroter
je supprime l'index + 1 car il est plus grand que l'index.

De cette façon on parcours beaucoup moins de fois le tableau, sur le tableau exemple ça à peu d'importance mais dans le cas ou tu as plusieurs centaines de lignes dans ton tableau ceci sera plus rapide.

pour éviter de renverser le tableau:

Code : Tout sélectionner

Local $Array[14] = [1000, 32, 200, 1000, 44, 400, 1000, 65, 60, 700, 1000, 72, 90, 80]

$cherche = _ArrayFindAll($Array, 1000)
_ArrayDisplay($cherche)

For $i = UBound($cherche) - 1 To 0 Step -1
    _ArrayDelete($Array, $cherche[$i] + 1)
    _ArrayDelete($Array, $cherche[$i])
Next
_ArrayDisplay($Array)
Voila
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11816
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#5

Message par Tlem »

Je ne vois pas ce qu'on reproche à la solution que j'ai donné ... :D

Test effectué sur un C2D 1.66Mhz avec XP Pro SP3 et un tableau de 100 éléments (la même ligne recopiée 7 fois + 2 éléments)

Temps de traitement pour ma solution : Environs 0.7 ms
Temps de traitement pour la dernière solution : Environs 20 ms :shock:
Pour la solution d'ani, environs 0.6 ms mais le résultat est faux. :lol:

Évidement pour un nombre d'éléments plus élevés, l'écart ce creuse encore plus :
Pour 1000 éléments : 4,5 ms contre 577 ms :P

EDIT : Une idée interressente, serait de tester un _ArrayToString, puis une expression régulière, puis de refaire l'array avec StringSplit.
Avis aux amateurs d'expressions régulières. ;)
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11816
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#6

Message par Tlem »

Bon ben je me répond tout seul. :lol:
Pour créer le pattern de l'expression régulière, je me suis inspiré des explications de notre ami sylvanie sur ce message.

Et voilà le résultat :

Code : Tout sélectionner

#Include <Array.au3>

Local $Array[14] = [1000, 32, 200, 1000, 44 , 400, 1000, 65 , 60, 700, 1000, 72, 90 , 80]

$Res = StringRegExpReplace(_ArrayToString($Array, ";"),"([^;]*1000;*[^;]*);","")
$Array = StringSplit($Res, ";")

_ArrayDisplay($Array,"")
:mrgreen:

Super cool les expressions régulières.
Bon par contre au niveau des performances, pour 1000 éléments cela me donne un traitement d'environs 5,4 ms ...
Même si c'est très légèrement moins rapide que ma première solution (1 ms), cela reste quand même la plus efficace et la plus élégante car elle tient sur deux lignes et retourne en plus dans l'élément 0 du tableau le nombre d'éléments renvoyés. ;)

Edit : Pour celui qui cherche la petite bête, il est possible de le faire en une seule ligne. :lol:

Code : Tout sélectionner

$Array = StringSplit(StringRegExpReplace(_ArrayToString($Array, ";"),"([^;]*1000;*[^;]*);",""), ";")
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
Avatar du membre
sylvanie
Niveau 11
Niveau 11
Messages : 1556
Enregistré le : jeu. 26 juil. 2007 21:31
Localisation : Paris
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#7

Message par sylvanie »

Bonjour, je n'ai pas eu le temps de poster hier soir, mais la version regexp n'est pas satisfaisante dans ce contexte (mais j'apprécis fortement que Tlem l'ai mis :) ).
En effet cete expression enlève tout élément comportant 1000 entre 2 ";" y compris 31000 par exple, donc on va enlever des tas de combinaison incluant 1000 dans la construction du nombre.

la bonne mouture est celle - ci (malheureuseument décomposée en 2 étapes car j'ai un petit soucis que je n'arrive pas à coprendre, mais là on s'écarterai franchement ...) :

Code : Tout sélectionner

$time3=TimerInit()
Local $Array[14] = [1000, 32, 200, 31000, 44 , 400, 1000, 65 , 60, 700, 1000, 72, 90 , 80]
ConsoleWrite(_ArrayToString($Array, ";")&@CRLF)
$Res = StringRegExpReplace(_ArrayToString($Array, ";"),"\A1000;","")
$Res = StringRegExpReplace($Res ,";1000;",";")
$Array = StringSplit($Res, ";")
ConsoleWrite(TimerDiff($time3)&@CRLF)
_ArrayDisplay($Array,"")
 
Bon du coups, niveau perf, on oublit ... :P , disons que là c'est un peu prendre un bazouka contre un moustique :mrgreen:
Toi qui cherche à mettre le doigt sur la solution, appuie sur F1.
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11816
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Supprimer une ligne d'un array en boucle

#8

Message par Tlem »

Une autre solution pour contourner le problème serait de remplacer toutes occurrence de ;1000;un nombre; par ;.
Le seul cas ou cela peut poser le problème c'est si 1000 est en début de tableau, mais dans ce cas lors de la conversion du tableau vers la chaîne, il suffit de rajouter un ";" en début de chaîne puis à la fin de supprimer le double ";" si il y à lieu. ;)

Edit : J'ai pas testé à fond, mais dans ce genre :

Code : Tout sélectionner

#Include <Array.au3>

Local $Array[14] = [1000, 32, 200, 1000, 44 , 400, 1000, 65 , 60, 700, 1000, 72, 31000 , 80]

$Res = StringRegExpReplace(";" & _ArrayToString($Array, ";"),"(;1000;*[^;]*);",";")
$Array = StringSplit(StringTrimLeft($Res, 1), ";")

_ArrayDisplay($Array,"")
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
eric
Niveau 5
Niveau 5
Messages : 177
Enregistré le : sam. 21 mars 2009 17:57
Localisation : Bretagne
Status : Hors ligne

Re: [R] Supprimer une ligne d'un array en boucle

#9

Message par eric »

Bonjour à tous.

Merci pour toutes ces propositions.

La suppression inversée de GaRydelaMer me convient tout à fait, en plus elle est rapide sur des gros Array.

C'était simple mais encore fallait il y penser :oops:
eric
Niveau 5
Niveau 5
Messages : 177
Enregistré le : sam. 21 mars 2009 17:57
Localisation : Bretagne
Status : Hors ligne

Re: [R] Supprimer une ligne d'un array en boucle

#10

Message par eric »

Par contre un _arraydelete c'est quand même lent parce que j'ai essayé sur un array de 30 000 lignes et ça n'en finit pas.

Si j'enlève l'_arraydelete, ça va super vite.

Mais c'est sur sans l'_arraydelete ça ne sert à rien.

:shock:

Y aurait il autre chose que l_arraydelete pour supprimer une ligne et qui fonctionne assez vite ?

Merci
Répondre