Löschen eines Arrays mit definierten Element(en) - Seite 8

 
Ich weiß nicht, was mt4 ist, es wird nicht einmal auf Win10 laufen, ich denke, das ist eine gute Sache
 
Maxim Dmitrievsky:
Ich weiß nicht, was mt4 ist, es wird nicht einmal auf Win10 laufen, ich denke, das ist eine gute Sache
Gut gesagt:)
 

Ich habe die Anordnung optimiert.

void OnStart()
{
     long array[], arr[] = {1, 2, 3, 6, 9, 5, 6, 3, 25, , , 6, 8, NULL, 7, NULL, 4, 45};
     ArrayCopy(array, arr); 
//--
  #ifdef __MQL5__
     Print( arrayFilter(array, array[2]) );
     ArrayPrint( array );
  #else
     string s = arrayFilter(array, array[2]) + " {";
     
     for(int i=0; i<ArraySize(array); i++)
     {
          s += array[i];
          if(i<ArraySize(array)-1)
               s += ", ";
     }
     
     Print( s+" }" );
  #endif
}
//---------------------------------------------------------------
template<typename T>
int arrayFilter(T &data[], const T value)
{
     int d = ArraySize(data), j = 0, y = 0;
     
     for(int i=0; i<d; i++, y++)
     {
          if(j>0)
               data[y] = data[y + j];
          
          if(data[i] == value || data[i] == NULL)
          {
               y--;
               j++;
          }
     }
  
     if(d > y)
          ArrayResize(data, y);
     
     return y;
}

Ich musste ArrayCopy verwenden, weilMQL5 schwor, dass das Array statisch war.


 
Nikolai Semko:

Wenn es so ein Schnelligkeitswettbewerb ist, werde ich meine eigene Variante anbieten...

Ihre Variante ist wirklich die schnellste, aber sie enthält einen Fehler: Wenn alle Elemente eines Arrays gleich einem Filter sind, wird Ihre Funktion das Array verlassen.

Ich werde meine eigene Variante anbieten, sie ist etwas langsamer als Ihre:

int ArrayModify(int &a[],const int v)
  {
   int size=ArraySize(a)-1;
   int j=0;
   int total=size;
   for(int i=0;i<size;i++)
     {
      while(a[i+j]==v && j<total)
        {
         j++;
         size--;
        }
      a[i]=a[i+j];
     }
   size=ArrayResize(a,size);
   return(size);
  }


2018.11.13 17:16:38.618 massiv v1 (EURUSD,M1) test my=1512090
2018.11.13 17:16:40.083 massiv v1 (EURUSD,M1) test alien=1464941

 
Vasiliy Sokolov:

Sie stellen diese Art von Fragen nun schon seit mehreren Jahren. Haben Sie viel gelernt? Es tut mir leid, aber es ist offensichtlich, dass Sie noch auf der Ebene von Bytes und elementaren Arrays sind.

Die Frage selbst ist falsch formuliert. Die Aufgabe besteht nicht darin, doppelte Werte zu entfernen (Aufgabe des GCE-Niveaus), sondern in etwas viel Größerem: Sie müssen die Liste der gültigen Elemente aktualisieren. Wenn ja, sollte die Frage ganz anders klingen. Sie verwirren und führen die Teilnehmer und vor allem sich selbst in die Irre: Sie drängen den Teilnehmern eine prinzipiell falsche Lösung auf und fordern sie auf, diese wirksam zu machen.

Ich programmiere nicht um des Programmierens willen, ich habe nicht das Ziel, ein Megaprogrammierer zu werden und in Foren schlau zu sein.

Was verstehen Sie an der Frage nicht: Ein Array mit definierten Elementen löschen?

 
Sergey Pavlov:

Ihre Variante ist in der Tat die schnellste, aber sie enthält einen Fehler: Wenn alle Elemente eines Arrays gleich einem Filter sind, wird Ihre Funktion das Array verlassen.

Ich schlage meine Variante vor, sie ist etwas langsamer als Ihre:


2018.11.13 17:16:38.618 massiv v1 (EURUSD,M1) test my=1512090
2018.11.13 17:16:40.083 massiv v1 (EURUSD,M1) test alien=1464941

Ja, danke. Korrigiert.

int ArrayDeleteVal(int &a[],const int val) // вариант Semko
  {
   int size=ArraySize(a);
   int i=0,start,s,count;
   while(i<size && a[i]!=val) i++; // ищем первый элемент массива со значением val
   if(i==size) return size;
   start=i; i++;  
   while(i<size && a[i]==val) i++; // ищем элемент массива со значением, не равным val
   if(i==size) {ArrayResize(a,0); return 0;}
   s=i; i++;
   while(true)
     {
      while(i<size && a[i]!=val) i++; // ищем элемент массива со значением val
      count=i-s;
      if(count>6) { ArrayCopy(a,a,start,s,count); start+=count;} // если нужно скопировать более 6 элементов, то имеет смысл воспользоваться ArrayCopy
      else for(; s<i; start++,s++) a[start]=a[s];                // иначе простой цикл
      if(i==size) break;
      i++;
      while(i<size && a[i]==val) i++; // ищем элемент массива со значением, не равным val
      if(i<size) s=i; else break;
      i++;
     }
   if(start<size) ArrayResize(a,start); else start=size;
   return(start);
  }

Nur haben Sie irgendwo auch einen Fehler, denn die Prüfsumme stimmt nicht überein, weil irgendwo ein Element fehlt. Ich habe nicht herausgefunden, wo.

2018.11.13 10:07:27.757 ArrayDeleteValue (EURUSD,D1)    вариант Pastushak: Контрольная сумма = 495782577; элементов - 999027; время выполнения = 156757 микросекунд
2018.11.13 10:07:27.761 ArrayDeleteValue (EURUSD,D1)    вариант Korotky:   Контрольная сумма = 495782577; элементов - 999027; время выполнения = 2338 микросекунд
2018.11.13 10:07:27.764 ArrayDeleteValue (EURUSD,D1)    вариант Fedoseev:  Контрольная сумма = 495782577; элементов - 999027; время выполнения = 1839 микросекунд
2018.11.13 10:07:27.766 ArrayDeleteValue (EURUSD,D1)    вариант Semko:     Контрольная сумма = 495782577; элементов - 999027; время выполнения = 782 микросекунд
2018.11.13 10:07:27.770 ArrayDeleteValue (EURUSD,D1)    вариант Pavlov:    Контрольная сумма = 495781718; элементов - 999026; время выполнения = 2886 микросекунд
2018.11.13 10:07:27.773 ArrayDeleteValue (EURUSD,D1)    вариант Nikitin:   Контрольная сумма = 495782577; элементов - 999027; время выполнения = 2355 микросекунд
Dateien:
 

Überflüssige Passagen wurden entfernt.

void OnStart()
{
     long array[], arr[] = {1, 2, 3, 6, 9, 5, 6, 3, 25, , , 6, 8, NULL, 7, NULL, 4, 45};
     ArrayCopy(array, arr);
//--
  #ifdef __MQL5__
     Print( arrayFilter(array, (long)3) );
     ArrayPrint( array );
  #else
     string s = arrayFilter(array, (long)3) + " {";
     
     for(int i=0; i<ArraySize(array); i++)
     {
          s += array[i];
          if(i<ArraySize(array)-1)
               s += ", ";
     }
     
     Print( s+" }" );
  #endif
}
//---------------------------------------------------------------
template<typename T>
int arrayFilter(T &data[], const T value=NULL)
{
     int d = ArraySize(data), y = 0;
     
     for(int i=0, j=0; i<d; i++, y++)
     {
          bool res = false;
          while(data[i] == value || data[i] == NULL)
          {
               res = true;
               j++;
            //---
               if(i+1==d)
                    break;
               if(data[i+1] == value || data[i+1] == NULL)
                    i++;
               else
                    break;
          }
          
          if(j>0)
          {
               if(d==y+j)
                    break;
               data[y] = data[y + j];
          }
          if(res)
               y--;
     }
  
     if(d > y)
          ArrayResize(data, y);
     
     return y;
}
 
Nikolai Semko:
In beiden Fällen wird jedes Element höchstens einmal gezogen.

Ich hatte gehofft, dass sich jemand für den DBMS-Ansatz interessiert und ihn ausprobiert, aber ich habe nicht gewartet. Ich musste es selbst tun.

int ArrayDelV (int &a[],const int val) { // вариант Vladimir
bool Flags[]; // массив пометок на удаление
int N, NewN, i, j;
N=ArraySize(a);
ArrayResize(Flags,N);
//if (ArrayInitialize(Flags,false)!=N) return(-1);
NewN=N; // Сколько останется
for (i=0;i<N;i++) {if (a[i]==val) {Flags[i]=true; NewN--;}}
j=0;
for (i=0;i<N;i++) {if (Flags[i]) {a[j]=a[i]; j++;}}
ArrayResize(a,NewN);
return(NewN);
}

Ich habe ArrayDeleteValue.mq5 in Ihren Checker eingefügt, er ist doppelt so schlecht wie Ihrer. Ich habe über den Grund nachgedacht und zwei Zeilen korrigiert, so dass ein Drittel der Einträge statt 0,1 % gelöscht werden.

   for(int i=0; i<1000000;i++) arr[i]=rand()%3;// 1000; //генерируем исходный массив случайными значениями от 0 до 1000
   int Value=rand()%3; // 1000; // значение, которое нужно удалить из массива

So ist es dann auch gekommen:

2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) Variante Pastushak: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 108521 Mikrosekunden
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) Variante Korotky: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 5525 Mikrosekunden
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) Variante Fedoseev: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 4879 Mikrosekunden
2018.11.13 19:45:22.164 Del (GBPUSD.m,H1) Variante Semko: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 14479 Mikrosekunden
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) Variante Pavlov: Checksumme = 998744; Elemente - 667421; Ausführungszeit = 0 Mikrosekunden
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) Variante Nikitin: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 5759 Mikrosekunden
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) Variante Vladimir: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 1542 Mikrosekunden

Die Variante von Pavlov hatte einen Fehler, den ich auskommentieren musste.

Fazit: Die Berechnung von Adressen in einem Array mit einem beliebigen Abstand zwischen ihren Nummern ist immer noch schlechter als die Verarbeitung von Elementen in einer Reihe, bei einem bestimmten Schritt, geschweige denn Schritt 1, kann der Compiler sie optimieren.

P.S. Borlands Pascal- und Delphi-Compiler machen es so, dass die Schleifenvariable zur Laufzeit keine Rolle spielt (im Speicher), sie wird irgendwo in den CPU-Registern abgelegt.

 
Vladimir:

Ich hatte gehofft, dass sich jemand für den DBMS-Ansatz interessiert und ihn ausprobiert, aber ich habe nicht gewartet. Ich musste es selbst tun.

Ich habe ArrayDeleteValue.mq5 in Ihren Checker eingefügt, er ist doppelt so schlecht wie Ihrer. Ich habe über den Grund nachgedacht und zwei Zeilen korrigiert, so dass ein Drittel der Einträge statt 0,1 % gelöscht werden.

So ist es dann auch gekommen:

2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) Variante Pastushak: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 108521 Mikrosekunden
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) Variante Korotky: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 5525 Mikrosekunden
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) Variante Fedoseev: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 4879 Mikrosekunden
2018.11.13 19:45:22.164 Del (GBPUSD.m,H1) Variante Semko: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 14479 Mikrosekunden
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) Variante Pavlov: Checksumme = 998744; Elemente - 667421; Ausführungszeit = 0 Mikrosekunden
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) Variante Nikitin: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 5759 Mikrosekunden
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) Variante Vladimir: Checksumme = 333586; Elemente - 667421; Ausführungszeit = 1542 Mikrosekunden

Die Variante von Pavlov hatte einen Fehler, den ich auskommentieren musste.

Fazit: Die Berechnung von Adressen in einem Array mit einem beliebigen Abstand zwischen ihren Nummern ist immer noch schlechter als die Verarbeitung von Elementen in einer Reihe in einem bestimmten Schritt, umso mehr in Schritt 1, der Compiler kann es optimieren.

P.S. Borlands Pascal- und Delphi-Compiler machen es so, dass die Schleifenvariable zur Laufzeit keine Rolle spielt (im Speicher), sie wird irgendwo in den CPU-Registern abgelegt.

Die Version von Pavlov wurde korrigiert.
Ihre Werte sind seltsam. Vielleicht haben Sie das Skript nach der Profilerstellung oder dem Debugger ausgeführt, ohne den Code neu zu kompilieren?
So funktioniert es bei mir:

2018.11.13 12:35:38.633 ArrayDeleteValue (EURUSD,D1)    вариант Pastushak: Контрольная сумма = 496494849; элементов - 999011; время выполнения = 131964 микросекунд
2018.11.13 12:35:38.636 ArrayDeleteValue (EURUSD,D1)    вариант Korotky:   Контрольная сумма = 496494849; элементов - 999011; время выполнения = 2310 микросекунд
2018.11.13 12:35:38.639 ArrayDeleteValue (EURUSD,D1)    вариант Fedoseev:  Контрольная сумма = 496494849; элементов - 999011; время выполнения = 1834 микросекунд
2018.11.13 12:35:38.641 ArrayDeleteValue (EURUSD,D1)    вариант Semko:     Контрольная сумма = 496494849; элементов - 999011; время выполнения = 773 микросекунд
2018.11.13 12:35:38.645 ArrayDeleteValue (EURUSD,D1)    вариант Pavlov:    Контрольная сумма = 496494849; элементов - 999011; время выполнения = 2815 микросекунд
2018.11.13 12:35:38.648 ArrayDeleteValue (EURUSD,D1)    вариант Nikitin:   Контрольная сумма = 496494849; элементов - 999011; время выполнения = 2475 микросекунд
2018.11.13 12:35:38.653 ArrayDeleteValue (EURUSD,D1)    вариант Vladimir:  Контрольная сумма = 496656342; элементов - 999011; время выполнения = 3608 микросекунд

Und in Ihrer Version erzeugt es eine falsche Prüfsumme. Und das Anlegen eines zusätzlichen Arrays bringt überhaupt nichts, im Gegenteil, es verlangsamt den Prozess und frisst zusätzliche Ressourcen.

Dateien:
 
Im Grunde genommen sind alle Algorithmen gleich. Jeder modifiziert das Array Element für Element, und jeder strebt die Fedoseev-Variante an, weil sie nichts Überflüssiges enthält.
Nur in meinem Fall ist es in Blöcken mit ArrayCopy getan, so gibt es einen Geschwindigkeitsvorteil.
Grund der Beschwerde: