Discussion de l'article "Le MQL5 Cookbook : Implémentation d'un tableau associatif ou d'un dictionnaire pour un accès rapide aux données" - page 4

 
Vasiliy Sokolov:

Il peut y avoir plusieurs raisons à cela. La plus probable est l'incompatibilité de type ou la mauvaise gestion des pointeurs. Nous ne pouvons pas non plus exclure les particularités du travail avec les méthodes template (il y a aussi leurs propres nuances).

En général, il est préférable d'utiliser un moteur de négociation prêt à l'emploi, ce qui vous permettra d'économiser beaucoup de temps et de nerfs : https://www.mql5.com/fr/articles/2166.

Bonjour, pouvez-vous me dire comment faire une boucle dans le dictionnaire entier, en supprimant les paires selon une certaine condition, quelque chose que je ne peux pas rattraper. Voici un exemple d'une telle tâche.

#include <Dictionary.mqh>

class CInt : public CObject
  {
public:
   int               value;
                     CInt(int _value = 0) : value(_value) {}
  };
  
CDictionary d;
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
int OnInit()
  {
   d.FreeMode(true);
   for(int i = 0; i < 10; ++i)
     {
      CInt *int_value = new CInt(i);
      d.AddObject(i, int_value);
     }
   for(CInt *node = d.GetFirstNode(); node != NULL;)
     {
      if(node.value % 2 == 0)
         // d.DeleteCurrentNode() ou d.DeleteObjectByKey(node.value) ;
         
      // Comment itérer dans le dictionnaire ???? 
     }
     
   return(INIT_SUCCEEDED);
  }
 
vek_y4icb:

Bonjour, Pouvez-vous me dire comment faire une boucle dans tout le dictionnaire, en supprimant les paires selon une certaine condition, quelque chose que je n'arrive pas à rattraper. Voici un exemple d'une telle tâche.

Bonne question. J'ai vérifié la suppression en utilisant votre méthode - elle ne fonctionne pas correctement. Je vais me pencher sur la question.

 
Vasiliy Sokolov:

Bonne question. J'ai vérifié la suppression à l'aide de votre méthode - elle ne fonctionne pas correctement. Je vais me pencher sur la question.

Cela ne devrait pas fonctionner correctement dans le cas général.

La bonne façon d'effectuer des suppressions multiples à partir d'un tableau associatif est de collecter un tableau de clés à supprimer, puis de procéder à une suppression par clé.

 
Andrei Trukhanovich:

il n'est pas nécessaire qu'il fonctionne correctement en général.

la bonne façon d'effectuer des suppressions multiples à partir d'un tableau associatif est de collecter un tableau de clés à supprimer, puis de supprimer par clé.

C'est compréhensible, mais encore une fois, c'est du travail inutile.

 
Vasiliy Sokolov:

Bonne question. J'ai vérifié la suppression à l'aide de votre méthode - elle ne fonctionne pas correctement. Je vais me pencher sur la question.

Merci pour votre réponse !

 
Andrei Trukhanovich:

il n'est pas nécessaire qu'il fonctionne correctement en général.

la bonne façon d'effectuer des suppressions multiples à partir d'un tableau associatif est de collecter un tableau de clés à supprimer, puis de supprimer par clé.

C'est là que le bât blesse, car même cette méthode provoque soudain un étrange bogue. Il s'agit manifestement d'une erreur. Je vais me pencher sur la question.

Pour l'instant, je peux vous conseiller de créer un nouveau dictionnaire, et d'y ajouter les valeurs qui ne doivent pas être supprimées. Ensuite, effacez l'ancien dictionnaire. Cela fonctionnera à 100 %.

 

Voici ce qu'il faut faire :

1. mettre à jour la version du dictionnaire avec celle qui est jointe à ce message.

2. Exécuter un script de test pour supprimer les éléments pairs.

La suppression doit se faire en deux passes :

int OnStart()
  {
   d.FreeMode(true);
   for(int i = 0; i < 10; ++i)
   {
      CInt *int_value = new CInt(i);
      d.AddObject(i, int_value);
   }
   //-- Créer une liste de clés à supprimer
   CArrayInt delKeys;
   for(CInt *node = d.GetFirstNode(); node != NULL; node = d.GetNextNode())
   {
      if(node.value % 2 == 0)
         delKeys.Add(node.value);
   }
   //-- Supprimer les objets assignés à la suppression, chacun séparément.
   for(int i = 0; i < delKeys.Total(); i++)
      d.DeleteObjectByKey(delKeys.At(i));
   for(CInt *node = d.GetFirstNode(); node != NULL; node = d.GetNextNode())
   {
      printf(node.value);
   }
     
   return(INIT_SUCCEEDED);
  }

En ce qui concerne la méthode DeleteCurrentObject():

Cette méthode ne doit être utilisée qu'en conjonction avec la fonction ContainsKey(). La seule raison pour laquelle elle est disponible en tant que méthode publique est que, dans ce cas, l'appel à la méthode permet de gagner du temps sur le repositionnement du pointeur. En d'autres termes, le seul cas typique d'utilisation de cette méthode est le suivant : 1. Vérifier s'il y a une clé, 2. si c'est le cas, la supprimer rapidement avec cette méthode.

Dossiers :
 
vek_y4icb:

C'est compréhensible, mais là encore, la carrosserie n'est pas nécessaire.

Il est techniquement possible de procéder à une dépose en un seul passage, comme vous le souhaitez. Mais ce serait compliqué. C'est pourquoi il n'est pas encore possible de le faire en deux passes. Du point de vue du dictionnaire en tant que structure de données distribuée, la suppression en deux passes est une solution plus correcte d'un point de vue canonique. Ce n'est qu'au niveau de l'utilisateur qu'il semble que la suppression est séquentielle, alors qu'en réalité tout est différent. En termes de performances, la suppression en une seule passe n'apportera aucun avantage. En termes de commodité, oui, elle peut être plus pratique.

 
Vasiliy Sokolov:

Il est techniquement possible de procéder à un retrait en un seul passage, comme vous le souhaitez. Mais ce serait compliqué. C'est pourquoi il n'est pas encore possible de procéder à une suppression en deux passes. Du point de vue du dictionnaire en tant que structure de données distribuée, la suppression en deux passes est plus correcte d'un point de vue canonique. Ce n'est qu'au niveau de l'utilisateur qu'il semble que la suppression est séquentielle, alors qu'en réalité tout est différent. En termes de performances, la suppression en une seule passe n'apporte aucun avantage. En termes de commodité, oui, elle peut être plus pratique.

Je vous remercie.

[Supprimé]  
Marcel Fitzner:

Je pense avoir trouvé un bug en supprimant un élément et en essayant d'atteindre le dernier élément :

L'erreur dans le CDictionary.mqh sera :

accès aupointeur invalide dans 'Dictionary.mqh' (463,9)

Quelqu'un peut-il le confirmer ? Comment corriger cette erreur ?



Il s'agit d'un bogue à la ligne 500 && 501 sur l'implémentation de la vérification des pointeurs.

Corrigé en utilisant la fonction intégrée CheckPointer().

Dossiers :
CDictionary.mqh  21 kb