Diskussion zum Artikel "Das MQL5-Kochbuch: Implementierung eines Assoziativen Arrays oder eines Lexikons für raschen Datenzugriff" - Seite 4

 
Vasiliy Sokolov:

Hierfür kann es mehrere Gründe geben. Höchstwahrscheinlich handelt es sich entweder um eine Typinkompatibilität oder eine falsche Handhabung von Zeigern. Auch können wir die Besonderheiten der Arbeit mit Vorlagenmethoden nicht ausschließen (auch hier gibt es eigene Nuancen).

Im Allgemeinen ist es besser, eine vorgefertigte Trading-Engine zu verwenden, Sie werden viel Zeit und Nerven sparen: https://www.mql5.com/de/articles/2166.

Guten Tag, können Sie mir sagen, wie ich eine Schleife durch das gesamte Wörterbuch machen kann, um Paare nach einer bestimmten Bedingung zu entfernen, etwas, das ich nicht nachvollziehen kann. Hier ist ein Beispiel für eine solche Aufgabe.

#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() oder d.DeleteObjectByKey(node.value);
         
      // Wie man durch das Wörterbuch iteriert???? 
     }
     
   return(INIT_SUCCEEDED);
  }
 
vek_y4icb:

Guten Tag, können Sie mir sagen, wie ich eine Schleife durch das gesamte Wörterbuch machen kann, um Paare nach einer bestimmten Bedingung zu entfernen, etwas, das ich nicht aufholen kann. Hier ist ein Beispiel für eine solche Aufgabe.

Gute Frage. Ich habe jetzt die Löschung mit Ihrer Methode überprüft - sie funktioniert nicht richtig. Ich werde es mir ansehen.

 
Vasiliy Sokolov:

Gute Frage. Ich habe jetzt die Löschung mit Ihrer Methode überprüft - sie funktioniert nicht richtig. Ich werde es mir ansehen.

Im allgemeinen Fall sollte es nicht korrekt funktionieren.

Der korrekte Weg, um mehrere Löschungen aus einem assoziativen Array durchzuführen, besteht darin, ein Array der zu löschenden Schlüssel zu sammeln und dann nach Schlüssel zu löschen.

 
Andrei Trukhanovich:

es muss im Allgemeinen nicht richtig funktionieren.

Der korrekte Weg, um mehrere Löschungen aus einem assoziativen Array durchzuführen, besteht darin, ein Array der zu löschenden Schlüssel zu sammeln und dann nach Schlüssel zu löschen.

Dies ist verständlich, aber auch hier ist es unnötige Arbeit.

 
Vasiliy Sokolov:

Gute Frage. Ich habe jetzt die Löschung mit Ihrer Methode überprüft - sie funktioniert nicht richtig. Ich werde es mir ansehen.

Vielen Dank für die Antwort!

 
Andrei Trukhanovich:

es muss im Allgemeinen nicht richtig funktionieren.

Der korrekte Weg, um mehrere Löschungen aus einem assoziativen Array durchzuführen, besteht darin, ein Array der zu löschenden Schlüssel zu sammeln und dann nach Schlüssel zu löschen.

Das ist die Sache, auch diese Methode verursacht plötzlich einen seltsamen Fehler. Es ist offensichtlich ein Fehler. Ich werde dem nachgehen.

Fürs Erste kann ich Ihnen raten, ein neues Wörterbuch zu erstellen und ihm die Werte hinzuzufügen, die nicht gelöscht werden müssen. Löschen Sie dann das alte Wörterbuch. Das wird zu 100% funktionieren.

 

So geht's:

1. Aktualisieren Sie die Version des Wörterbuchs auf die an diesen Beitrag angehängte Version.

2. Führen Sie ein Testskript aus, um auch Elemente zu löschen.

Die Löschung sollte in zwei Durchgängen erfolgen:

int OnStart()
  {
   d.FreeMode(true);
   for(int i = 0; i < 10; ++i)
   {
      CInt *int_value = new CInt(i);
      d.AddObject(i, int_value);
   }
   //-- Erstellen einer Liste der zu löschenden Schlüssel
   CArrayInt delKeys;
   for(CInt *node = d.GetFirstNode(); node != NULL; node = d.GetNextNode())
   {
      if(node.value % 2 == 0)
         delKeys.Add(node.value);
   }
   //-- Löschen Sie die zur Löschung zugewiesenen Objekte, jedes für sich.
   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);
  }

Bezüglich der Methode DeleteCurrentObject():

Diese Methode sollte nur in Verbindung mit der Funktion ContainsKey() verwendet werden. Der einzige Grund, warum sie als öffentlich verfügbar ist, ist, dass der Methodenaufruf in diesem Fall Zeit bei der Neupositionierung des Zeigers spart. Das heißt, der typische und einzige Fall seiner Verwendung ist 1. Prüfen, ob ein Schlüssel vorhanden ist, 2. wenn ja, diesen schnell mit dieser Methode löschen.

Dateien:
 
vek_y4icb:

Das ist zwar verständlich, aber auch wieder unnötige Karosseriearbeit.

Es ist technisch möglich, den Ausbau in einem Arbeitsgang durchzuführen, wie Sie es erwarten. Aber es wäre kompliziert. Deshalb noch nicht, nur in zwei Durchgängen. Aus der Sicht des Wörterbuchs als verteilte Datenstruktur ist die Löschung in zwei Durchgängen eine kanonisch korrektere Lösung. Nur auf der Benutzerebene sieht es so aus, als ob die Löschung sequentiell erfolgt, in Wirklichkeit ist alles anders. In Bezug auf die Leistung bringt die Löschung in einem Durchgang keine Vorteile. Was die Bequemlichkeit angeht, so kann es durchaus bequemer sein.

 
Vasiliy Sokolov:

Es ist technisch möglich, die Entfernung in einem Durchgang durchzuführen, wie Sie erwarten. Aber es wäre kompliziert. Deshalb noch nicht, nur in zwei Durchgängen. Aus der Sicht des Wörterbuchs als verteilte Datenstruktur ist die Löschung in zwei Durchgängen kanonisch korrekter. Nur auf der Benutzerebene sieht es so aus, als ob die Löschung sequentiell erfolgt, in Wirklichkeit ist alles anders. In Bezug auf die Leistung bringt das Löschen in einem Durchgang keine Vorteile. Was die Bequemlichkeit angeht, so kann es durchaus bequemer sein.

Ich danke Ihnen.

[Gelöscht]  
Marcel Fitzner:

Ich glaube, ich habe einen Fehler gefunden, wenn ich ein Element lösche und versuche, zum letzten Element zu gelangen:

Fehler in der CDictionary.mqh wird sein:

ungültiger Zeigerzugriff in 'Dictionary.mqh' (463,9)

Kann jemand dies bestätigen? Hat jemand eine Idee, wie man das beheben kann?



Es war ein Fehler in Zeile 500 && 501 bei der Implementierung der Zeigerüberprüfung.

Behoben mit der eingebauten CheckPointer().

Dateien:
CDictionary.mqh  21 kb