Array encapsulé dictionnaire et suppression data selon valeur de l'item
Bonsoir tout le monde,
J'ai besoin d'une aide, davantage en terme de logique que de code, s'il vous plait.
Pour mon besoin je dois boucler sur les data d'un dictionnaire "dicodate" (classé décroissant selon son dernier item mais peu importe).
Voici un extrait des items dans l'illustration.
Voici un extrait de mon code. Cela n'apparait pas mais il est déjà intégré dans une boucle de type : for i = 0 to lastrow d'un tableau qui, en colonne R contient une clé "clé 34". En colonne 19 on veut transférer la première valeur de la "clé 28" trouvée dans le dictionnaire.
Puis supprimer toutes les entrées du dictionnaire qui ont comme item la "clé 34" ou la "clé 28" en référence : pour cela je me sers de la clé primaire de type "clé 34" & "clé 28" (les deux font toujours 9 caractères).
Puis poursuivre la boucle, MAIS ... ca chie.
a = dicodate.keys: b = dicodate.items
For j = (dicodate.Count - 1) To 0 Step -1
i = [R:R].Find(What:=b(j)(0), LookAt:=xlPart).Row
If Not Cells(i, 19) = "" Then
Cells(i, 19) = Cells(i, 19).Value & ";" & b(j)(1)
Else
Cells(i, 19) = b(j)(1)
End If
For Each k In dicodate.keys
If Left(a(k), 9) = b(j)(0) Then dicodate.Remove a(k)
If Right(a(k), 9) = b(j)(1) Then dicodate.Remove a(k)
a = dicodate.keys
Next k
b = dicodate.items
Next jAvez-vous une idée ?
Note personnelle : le plus évident pour mon besoin me semble de constituer un dictionnaire des "clé 34" et "clé 28" déjà utilisées. Et à la place de remove qui bouscule l'indexation du dictionnaire, si la clé existe déjà dans ce dictionnaire, il faut simplement next j ...
Bonjour,
Hum pas certain que ton sujet soit très parlant.
Ce qui serait intéressant serait d'avoir un aperçu du problème complet pas de la manière avec laquelle tu n'arrives pas à le résoudre.
Le minimum serait qu'on ait une jeu de données représentatif pour tester.
Ensuite "ça chie" n'est pas une explication que se passe -t-il réellement ?
Rappel : Les suppressions dans les Array et autres listes se font en partant de la dernière occurence, justement pour ne pas "casser l'indexation" donc pas avec
For Each k In dicodate.keys
'mais
for k =dicodate.count to 1 step -1Bon enfin cette dernière remarque c'est à vu de nez... hein !
A+
bonjour galopin01,tomato,
un essai sans fichier ....
Sub test()
Dim Dict_Cles, Dict, aA, aOut, N
Set Dict_Cles = CreateObject("scripting.dictionary")
Set Dict = CreateObject("scripting.dictionary")
aA = Range("Tabel").ListObject.DataBodyRange
For i = 1 To UBound(aA)
If Not Dict_Cles.exists("34|" & aA(i, 1)) Then 'nouveau clé 34
Dict_Cles("34|" & aA(i, 1)) = aA(i, 2)
Dict_Cles("28|" & aA(i, 2)) = aA(i, 1)
End If
If Dict_Cles("34|" & aA(i, 1)) <> aA(i, 2) Then
If Not Dict_Cles.exists("28|" & aA(i, 2)) Then
Dict.Add Dict.Count, Array(aA(i, 1), aA(i, 2), aA(i, 3), aA(i, 4))
End If
End If
Next
N = Dict.Count
If N = 1 Then Dict.Add [Rnd], Dict.items()(0)
If N > 0 Then
aOut = Application.Index(Dict.items, 0, 0)
Range("AA1").Resize(N, UBound(aOut, 2)).Value = aOut
Else
Range("AA1").Resize(100, 4).ClearContents
End If
End SubBonjour,
Comme Galopin j'ai assez de mal à me figurer le problème, peut etre un peu trop abstrait pour etre expliqué simplement.
Je commente aussi pour suite le fil, mais si jamais il m'est arrivé de travailler avec des recherches complexes de clés/indexes puis suppressions tout cela dans des boucles récursives sur de très longues listes…
Pour éviter les problèmes d'indexations lors des .Remove, mais en souhaitant conserver la liste initiale pour ne pas "perdre de temps" à la recalculer, j'ai trouvé qu'une solution intéressante était de créer une seconde ArrayList des clés disponibles, et boucler, de la facon expliquée par Galopin sur celle-ci. Ainsi le dictionnaire initial n'est pas modifié, simplement on applique un "masque" sur les indexes à filtrer.
L'implémentation était pour des calculs de projections de plans en 3D les uns sur les autres, d'où le besoin de récursivité. Cependant si votre projet ne comprend pas de récursion, je pense que vous pouvez vous en sortir de manière plus simple.
Bonsoir à tous,
La réponse était effectivement dans la question : on ne supprime évidemment pas les entrées d'un dictionnaire par le début mais par la fin.
Règle de base dont on ne peut échapper qu'en trichant : et en créant un dictionnaire supplémentaire qui répertoriera les clés à supprimer mais une fois seulement, après la fin de la boucle. Bref rien que du très évident.
J'ai été surpris, un peu ému et surtout très embêté de vous avoir fait mouliner sur ce sujet pour lequel j'ai en plus entrepris de changer totalement d'approche. En m'excusant de ne pouvoir vous en dire davantage sur le but de la manoeuvre (explication longue, et qui nécessite l'appuie d'un jeu de données, sensibles, massives et que je vous avoue n'avoir pas le courage d'anonymiser).
Merci à Galopin01, BsAlv et saboh12617