Retirer un élément d'un Array

Bonjour,

Je cherche à retirer un élément d'un Array. Actuellement j'utilise le code suivant assez consommateur de temps quand l'Array est de dimension importante et la procédure répétée des centaines de milliers de fois. Y'a-t-il moyen d'éviter cela ?

Sub RetirerElementArray()
    Dim r2()
    r1 = Array(0, 1, 2, 3, 4, 5)
    Aretirer = 2
    cpt = -1
    For i = 0 To UBound(r1)
        If r1(i) <> Aretirer Then
            cpt = cpt + 1
            ReDim Preserve r2(cpt)
            r2(cpt) = r1(i)
        End If
    Next i
    ' r2 = Array(0, 1, 3, 4, 5)
End Sub

Merci par avance

Bonsoir,

Code de @lermite, un peu plus court que le votre :

Fonction :

Sub SuppErg(TB(), ERG As Integer)
Dim i As Integer
    For i = ERG To UBound(TB) - 1
        TB(i) = TB(i + 1)
    Next i
    ReDim Preserve TB(i - 1)
End Sub

Ligne de code dans votre programme :

SuppErg MyArray(), 3

Cela permet d'être plus rapide ?

Baboutz

Bonjour,

J'ai une petite idée avec un élément unique :

Sub RetirerElementArray()

Dim Aretirer
Dim r2()
Dim chaine$

Aretirer = 2 'mon élément unique, ici 2
r1 = Array(0, 1, 2, 3, 4, 5)
chaine = replace(join(r1, "/\/"), Aretirer & "/\/", "")  ' "/\/" est un séparateur arbitraire qui ne devrait pas se retrouver ailleurs dans la chaine
'ici, on transforme en chaine puis on remplace la partie à supprimer
r2 = split(chaine, "/\/") 'on remet en tableau

End Sub

Seulement, il y a de fortes chances que les éléments soient de type string après cette opération. C'est donc une solution pour des tableaux de chaines surtout...

Cordialement,

Bonjour Stéphane1972,

Utiliser un Array string dont les termes seront converti en integer ensuite.

Comme ci-dessous.

Sub RetirerElementArray()
    Dim r2() As String
    r1 = Array("0", "1", "2", "3", "4", "5")
    r2 = Filter(r1, "2", False)
     For j = 0 To UBound(r2)
    Cells(j + 1, "A") = CInt(r2(j))
    Next j
End Sub

Merci à vous trois,

Baboutz je n'ai pas réussi à faire fonctionner ton code mais cela pourrait être intéressant, pour rester fidèle à mon exemple j'ai tenté :

Call SuppErg(Array(0, 1, 2, 3, 4, 5), 2)

Merci 3GB tu auras introduit dans mon vocabulaire VBA les mots : Join et Split mais…

Merci X-Cellus tu auras introduit dans mon vocabulaire VBA le mot Filter mais…

… mon Array est en fait constitué de sous-arrays :

r1 = array(array(1,1,0),array(-1,1,0),...)

Excusez-moi d'avoir essayé de simplifier le problème et vous avoir induit en erreur.

Cordialement

Re-bonjour,

J'ai obtenu beaucoup de réponses à mon sujet et j'en remercie les auteurs. Malheureusement j'avais cherché à simplifier l'exposé du problème et je ne peux pas exploiter ces réponses. Mon Array principal est en fait constitué de Sous-Arrays composé de 3 Integers. Revoici donc l'intégralité du problème re-posé, plus aucune simplification cette fois-ci :

Function RetirerElementArray(ArraySource, SousArray)
    Dim ArrayResultat()
    cpt = -1
    For i = 0 To UBound(ArraySource)
        asi = ArraySource(i)
        If asi(0) <> SousArray(0) And asi(1) <> SousArray(1) And asi(2) <> SousArray(2) Then
            cpt = cpt + 1
            ReDim Preserve ArrayResultat(cpt)
            ArrayResultat(cpt) = ArraySource(i)
        End If
    Next i
    RetirerElementArray = ArrayResultat
End Function

Sub test()
    r = RetirerElementArray(Array(Array(2, 5, 8), Array(40, 3, 803), Array(51, 12, 29), Array(10, 0, 48)), Array(40, 3, 803))
    Stop
    ' r = Array(Array(2, 5, 8), Array(51, 12, 29), Array(10, 0, 48))
End Sub

Sachant que RetirerElementArray peut être répétée des dizaines voire des centaines de milliers de fois et que ArraySource comporte presque autant d'éléments, cette procédure peut s'avérer très coûteuse en temps. SousArray est toujours un Array composé de 3 Integers

Dans ce Post Klin89 propose une alternative intéressante à

If asi(0) <> SousArray(0) And asi(1) <> SousArray(1) And asi(2) <> SousArray(2) Then

Mais si elle est d'une écriture plus simple et plus belle elle s'avère plus coûteuse en temps aussi je pense que cette ligne-là ne peut pas être optimisée.

J'espère que je n'aurais pas dissuadé les bonnes volontés pour m'aider avec mon erreur initiale.

Avec gratitude

Bonjour Stéphane1972

Vas voir du coté de Arraylist et des méthodes RemoveAt et IndexOf

klin89

Bonjour,

lorsque tu mets 3 tests sur la même ligne ils sont tous exécuter.
Il faut les séparer, si le 1er est négatif inutile de faire les autres.

Ca plus éliminer les variables dont on peut se passer (chaque affectation coûte) et le typage des variables, j'arrive à un gain de 20%
Päs mirobolant mais toujours ça de pris.

Sub test()
    Dim t As Single
    t = Timer
    For i = 1 To 10000
        r = RetirerElementArray(Array(Array(2, 5, 8), Array(40, 3, 803), Array(51, 12, 29), Array(10, 0, 48)), Array(40, 3, 803))
        ' r = Array(Array(2, 5, 8), Array(51, 12, 29), Array(10, 0, 48))
    Next i
    Debug.Print Timer - t
End Sub

Function RetirerElementArray(ArraySource, SousArray)
    Dim ArrayResultat()
    Dim i As Long, j As Long
    For i = UBound(ArraySource) To 0 Step -1
        If ArraySource(i)(0) = SousArray(0) Then
            If ArraySource(i)(1) = SousArray(1) Then
                If ArraySource(i)(2) = SousArray(2) Then
                    For j = i To UBound(ArraySource) - 1
                        ArraySource(j) = ArraySource(j + 1)
                    Next j
                    ReDim Preserve ArraySource(UBound(ArraySource) - 1)
                End If
            End If
        End If
    Next i
    RetirerElementArray = ArraySource
End Function

et si chaque sous array ne peut être présent 2 fois, ajouter un exit for après le redim preserve pour un gain supplémentaire.
Si par contre il peut être présent plusieurs fois, il vaudra mieux les compter et faire un unique redim preserve après la boucle
eric

Bonjour,

moi j'utiliserais un dictionnaire.

Bonjour h2so4,

J'ai du mal à imaginer un gain avec un dictionnaire vu qu'il faudra de toute façon lire tout le tableau et supprimer les indésirables.
Soit la même chose qu'actuellement avec plus de lignes, à moins que tu n'aies autre chose en tête ?

Moi ce que je vois c'est qu'on a que le petit bout de la lorgnette. Si ses données sont issues d'une feuille il y aura peut-être d'autres possibilités plus performantes.

Ca serait bien d'avoir le point de départ, le besoin et les contraintes pour avoir une vue plus large.
Par ailleurs si ses suppressions multiples peuvent être passées par un tableau, peut-être que des gains sont possibles. Des tests pourraient y répondre

Bonjour à tous,

Juste pour info, pour retirer un élément d'un tableau on peut faire court :

Dim T As Variant

    T = Filter(Array(0, 1, 2, 3, 4, 5), 2, False)

Ici pour enlever le '2' du tableau (0, 1, 2, 3, 4, 5)

Pierre

bonjour eriiic

Moi ce que je vois c'est qu'on a que le petit bout de la lorgnette. Si ses données sont issues d'une feuille il y aura peut-être d'autres possibilités plus performantes.

effectivement, Peut-être peut-on même se passer de la suppression mais simplement mettre un indicateur de données supprimées.

pour le dictionnaire, l'idée est de

- initialisation :

charger le tableau dans un dictionnaire (la clé étant la concaténation des 3 éléments de l'array). l'item associé étant l'array de 3 éléments.

- boucle : on peut répéter la phase suivante à l'envi

- on fait les suppressions dans le dictionnaire des clés qui ne nous interessent plus,

- une fois les suppressions terminées, on charge les items dans le tableau initial.

-on utilise le tableau pour ce que l'on a à faire

- on recommence en boucle si nécessaire (dictionnaire et tableau sont synchronisés)

je pense que cela doit aller plus vite (recherche des valeurs à supprimer et réorganisation du tableau, surtout si beaucoup de valeurs)

arraylist (proposé par klin89) me semble aussi une piste intéressante à envisager

A voir oui.
Mais bon, faire des tests sur 4 lignes alors que des milliers sont prévues n'est pas du tout représentatif.
Il y a parfois des effets de seuil inattendus.
Le demandeur devrait faire un effort de ce coté.

Bonsoir,

Que de réponses ! Et il y a de la matière ! Un grand merci à vous tous.

L'échange entre eriiic et h2so4 est un peu de haute volée pour moi, j'essaierai de comprendre cette histoire de dictionnaire après avoir étudié la solution de Klin89. Merci à eriiic pour son optimisation de ma procédure pour un gain de 20% c'est intéressant à prendre

h2so4 je suis ravi de faire ta connaissance, LouReeD m'a confié un algorithme écrit par toi et que j'ai commencé à étudier de Pathfindage et c'est ma grande passion du moment. Nous aurons peut-être l'occasion d'échanger sur le sujet ?

Stéphane

Bonjour,

voici quelques tests qui illustrent l'idée que j'avais, ainsi qu'une adaptation du code d'eriiic (utilisation d'une sub et byref). 3 macros à comparer. aargh(dictionnaire, test macro d'eriiic, test1 macro d'eriiic adaptée)

Bonjour,

effectivement, joli gain (/3). Je n'avais aucune idée de ce qu'il pouvait être.
Bravo :-)
eric

Rechercher des sujets similaires à "retirer element array"