SUPPRIMER UN ITEM DANS UN TABLEAU EN LE PARCOURANT UNE SEULE FOIS
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 2021
-
18 août 2010 à 05:52
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 2021
-
19 août 2010 à 09:02
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 19 août 2010 à 09:02
j'ajouterais concernant les Strings qu'il n'y as pas systematiquement de test a faire pour éviter les chaines vides...
tout dépend de ce à quoi l'on déstine le tableau...
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 19 août 2010 à 09:00
quand je parles de compact, je veux dire de faire la recopie des elements renseignés dans le tableau, en laissant de coté les "cases" vides.
je ne parlais donc pas d'une fonction intégrée quelconque.
Il est possible de faire, donc, un CopyMemory pour décaler rapidement les données.
l'astuce consistera a ne pas redimensionner le tableau tout de suite, et de le faire plus tard (possible de conserver une variable contenant le nombre d'elements du tableau)
Mais bon, il faut bien cibler la problématique, ce n'est pas si courant que cela de devoir supprimer des items d'un tableau.
Khun Dun
Messages postés3Date d'inscriptionmercredi 22 décembre 2004StatutMembreDernière intervention19 août 2010 19 août 2010 à 08:58
le test supplémentaire prendra toujours moins de temps que les recopiages de tableaux ou encore l'utilisation parfois risquée d'un API
c'est garantit ! j'ai fais des tests de performance par rapport à ça, à cause d'un projet qui utilisait les tableaux de façon presque abusive ^^ le gain de temps est non négligeable
andalo
Messages postés102Date d'inscriptionlundi 23 avril 2007StatutMembreDernière intervention20 octobre 2012 19 août 2010 à 08:53
je ne connaissais pas l'API copymemory, du coup j'ai trouvé ca :
la problématique est d'insérer une valeur mais ca se ressemble. Pour dire vrai j'avoue ne pas avoir pigé comment me servir de ces infos pour le moment.
faire un compact sur un tableau, ca non plus je ne connais pas, Renfield, si tu peux m'éclairer je suis preneur.
la méthode a Khun Dun est tentante. Mais je me demande si c'est si optimisé que ca. au moment de la suppression il n'y a pas photo. Mais au moment de la relecture du tableau, il faut ajouter un test supplémentaire à la lecture de chaque entrée. Le gain est il réel du coup?
Sehnsucht, effectivement il y a deux boucles, mais un seul parcours du tableau, il faut que je change le titre! peut tu expliquer cette ligne :
Dim index = Array.IndexOf(Of T)(source, toDelete)
et surtout a t'elle une équivalence en VB6?
si je comprend bien, elle te permet de retrouver l'index dans le tableau de la valeur a supprimer sans le parcourir.
Khun Dun
Messages postés3Date d'inscriptionmercredi 22 décembre 2004StatutMembreDernière intervention19 août 2010 19 août 2010 à 08:52
alors dans ce cas je créé un Type
Private Type tInfo
Value As Integer
Tag As Integer
End Type
Private mTableau(10) As tInfo 'on peut faire un tableau variable aussi
ensuite je remplie comme d'habitude mon tableau en utilisant Tableau(Index).Value = [integer]
et lorsque je souhaite effacer une valeur, je remplie le Tag avec par exemple -1
il suffit donc, quand on lit le tableau, de lire que les Tag différents de -1
Sehnsucht
Messages postés107Date d'inscriptionsamedi 25 novembre 2000StatutMembreDernière intervention 4 mai 2013 19 août 2010 à 01:09
C'est bien pour un tableau de String (ou autre type référence) mais pour un tableau d'Integer (ou autre type valeur) ?
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 18 août 2010 à 23:56
j'approuve.
tout depend de l'usage...
ca evite de decaler les index...
et rien n'empeche de faire un Compact par la suite, pour recreer un tableau avec les valeurs non vides...
Khun Dun
Messages postés3Date d'inscriptionmercredi 22 décembre 2004StatutMembreDernière intervention19 août 2010 18 août 2010 à 23:27
moi j'ai une solution extrêmement simple et qui est nettement plus rapide comparée à ce qui est proposé ici, quand je veux supprimer une valeur de mon tableau je fais tableau(index)="" et quand j'ai besoin de lire mon tableau je ne lis que les valeurs différentes de "" tout simplement, sincèrement ça a l'air stupide comme ça, mais c'est ce qu'il y a de mieux pratiquement lorsqu'on a besoin d'optimisation
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 18 août 2010 à 19:01
Redim preserve ne fait pas obligatoirement de recopie... surtout dans le cas d'une reduction de taille.
l'exemple propose est en .Net, mais avec un CopyMemory, on peut arriver au meme code.
Sehnsucht
Messages postés107Date d'inscriptionsamedi 25 novembre 2000StatutMembreDernière intervention 4 mai 2013 18 août 2010 à 18:34
Je vois, malgré cela tu as quand même deux boucles même si la 2ème est imbriquée dans la 1ère, de plus le ReDim Preserve fais une copie de ton tableau en mémoire ce qui peut s'avérer lourd dans le cas d'un grand tableau.
Personnellement j'utilise une autre méthode, d'ailleurs je ne sais pas trop ce qu'elle vaut, si j'ai le temps je me ferais un petit benchmark mais je la poste ici des fois que...
Sub Remove(Of T)(ByRef source As T(), ByVal toDelete As T)
If source Is Nothing Then Exit Sub
Dim index = Array.IndexOf(Of T)(source, toDelete)
If index = -1 Then Exit Sub
Dim temp(source.Length - 2) As T
Array.ConstrainedCopy(source, 0, temp, 0, index)
Array.ConstrainedCopy(source, index + 1, temp, index, source.Length - index - 1)
source = temp
End Sub
Cordialement !
andalo
Messages postés102Date d'inscriptionlundi 23 avril 2007StatutMembreDernière intervention20 octobre 2012 18 août 2010 à 15:03
Quand je me suis confronté au problème et que j'ai cherché sur ce site je n'ai trouvé que des solutions imposant de créer un deuxième tableau à remplir lors d'une première itération,et une deuxième itération pour re-remplir le premier tableau à partir du deuxième.Comme, pour une fois je me suis trouvé pas trop bête en faisant ca en une seule boucle, j'ai trouvé que ca optimisais un peu.
Sehnsucht
Messages postés107Date d'inscriptionsamedi 25 novembre 2000StatutMembreDernière intervention 4 mai 2013 18 août 2010 à 13:18
Bonjour,
Au risque de poser une question stupide (ça ne serait pas la première fois ^^),
en quoi ce code est-il optimisé (c'est une vraie question) ?
Cordialement !
andalo
Messages postés102Date d'inscriptionlundi 23 avril 2007StatutMembreDernière intervention20 octobre 2012 18 août 2010 à 08:52
très juste, je corrige
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 18 août 2010 à 05:52
assures toi bien que ton tableau n'a pas qu'une seule entree...
19 août 2010 à 09:02
tout dépend de ce à quoi l'on déstine le tableau...
19 août 2010 à 09:00
je ne parlais donc pas d'une fonction intégrée quelconque.
Il est possible de faire, donc, un CopyMemory pour décaler rapidement les données.
l'astuce consistera a ne pas redimensionner le tableau tout de suite, et de le faire plus tard (possible de conserver une variable contenant le nombre d'elements du tableau)
Mais bon, il faut bien cibler la problématique, ce n'est pas si courant que cela de devoir supprimer des items d'un tableau.
19 août 2010 à 08:58
c'est garantit ! j'ai fais des tests de performance par rapport à ça, à cause d'un projet qui utilisait les tableaux de façon presque abusive ^^ le gain de temps est non négligeable
19 août 2010 à 08:53
http://www.vbfrance.com/forum/sujet-TABLEAUX-CHAINES-COPYMEMORY-QUAND-POTENCE-VOUS-GUETTE_1234952.aspx
la problématique est d'insérer une valeur mais ca se ressemble. Pour dire vrai j'avoue ne pas avoir pigé comment me servir de ces infos pour le moment.
faire un compact sur un tableau, ca non plus je ne connais pas, Renfield, si tu peux m'éclairer je suis preneur.
la méthode a Khun Dun est tentante. Mais je me demande si c'est si optimisé que ca. au moment de la suppression il n'y a pas photo. Mais au moment de la relecture du tableau, il faut ajouter un test supplémentaire à la lecture de chaque entrée. Le gain est il réel du coup?
Sehnsucht, effectivement il y a deux boucles, mais un seul parcours du tableau, il faut que je change le titre! peut tu expliquer cette ligne :
Dim index = Array.IndexOf(Of T)(source, toDelete)
et surtout a t'elle une équivalence en VB6?
si je comprend bien, elle te permet de retrouver l'index dans le tableau de la valeur a supprimer sans le parcourir.
19 août 2010 à 08:52
Private Type tInfo
Value As Integer
Tag As Integer
End Type
Private mTableau(10) As tInfo 'on peut faire un tableau variable aussi
ensuite je remplie comme d'habitude mon tableau en utilisant Tableau(Index).Value = [integer]
et lorsque je souhaite effacer une valeur, je remplie le Tag avec par exemple -1
il suffit donc, quand on lit le tableau, de lire que les Tag différents de -1
19 août 2010 à 01:09
18 août 2010 à 23:56
tout depend de l'usage...
ca evite de decaler les index...
et rien n'empeche de faire un Compact par la suite, pour recreer un tableau avec les valeurs non vides...
18 août 2010 à 23:27
18 août 2010 à 19:01
l'exemple propose est en .Net, mais avec un CopyMemory, on peut arriver au meme code.
18 août 2010 à 18:34
Personnellement j'utilise une autre méthode, d'ailleurs je ne sais pas trop ce qu'elle vaut, si j'ai le temps je me ferais un petit benchmark mais je la poste ici des fois que...
Sub Remove(Of T)(ByRef source As T(), ByVal toDelete As T)
If source Is Nothing Then Exit Sub
Dim index = Array.IndexOf(Of T)(source, toDelete)
If index = -1 Then Exit Sub
Dim temp(source.Length - 2) As T
Array.ConstrainedCopy(source, 0, temp, 0, index)
Array.ConstrainedCopy(source, index + 1, temp, index, source.Length - index - 1)
source = temp
End Sub
Cordialement !
18 août 2010 à 15:03
18 août 2010 à 13:18
Au risque de poser une question stupide (ça ne serait pas la première fois ^^),
en quoi ce code est-il optimisé (c'est une vraie question) ?
Cordialement !
18 août 2010 à 08:52
18 août 2010 à 05:52