Effacement d'un tableau d'élément(s) défini(s) - page 8

 
je ne sais pas ce qu'est mt4, il ne fonctionne même pas sur win10, je pense que c'est une bonne chose
 
Maxim Dmitrievsky:
je ne sais pas ce qu'est mt4, il ne fonctionne même pas sur win10, je pense que c'est une bonne chose
Bien dit :)
 

J'ai modifié le tableau.

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;
}

J'ai dû utiliser ArrayCopy , carMQL5 jurait que le tableau était statique.


 
Nikolai Semko:

Si c'est un concours de rapidité, je vais proposer ma propre variante...

Votre variante est effectivement la plus rapide, mais elle contient un bug : si tous les éléments d'un tableau sont égaux à un filtre, votre fonction sortira du tableau.

Je vais proposer ma propre variante, elle est un peu plus lente que la vôtre :

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:

Cela fait plusieurs années que vous posez ce genre de questions. Avez-vous appris beaucoup de choses ? Désolé, mais il est évident que vous en êtes encore au niveau des octets et des tableaux élémentaires.

La question elle-même est formulée de manière incorrecte. La tâche n'est pas de supprimer les valeurs répétitives (tâche de niveau GCE) mais dans quelque chose de beaucoup plus grand, vous devez mettre à jour la liste des éléments valides. Si c'est le cas, la question devrait être complètement différente. Vous confondez et trompez les participants et, avant tout, vous-même : imposez aux participants la mauvaise solution de principe et demandez de la rendre effective.

Je ne fais pas de la programmation pour le plaisir de programmer, je n'ai pas pour objectif de devenir un méga-programmeur et de faire le malin sur les forums.

Qu'est-ce que vous ne comprenez pas dans la question : Effacer un tableau d'éléments définis ?

 
Sergey Pavlov:

Votre variante est effectivement la plus rapide, mais elle contient un bug : si tous les éléments d'un tableau sont égaux à un filtre, votre fonction sortira du tableau.

Je vais proposer ma variante, elle est un peu plus lente que la vôtre :


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

Oui, merci. Corrigé.

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);
  }

Seulement, vous avez aussi une erreur quelque part, car la somme de contrôle ne coïncide pas parce qu'il manque un élément quelque part. On ne sait pas où.

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 микросекунд
Dossiers :
 

Ajusté en supprimant les passages inutiles

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:
Dans les deux cas, chaque élément est traîné au maximum une fois.

Oui, désolé, une seule fois en effet. J'espérais que quelqu'un serait intéressé par l'approche SGBD et vérifierait, je n'ai pas attendu. J'ai dû le faire moi-même.

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);
}

J'ai inséré ArrayDeleteValue.mq5 dans ton vérificateur, il est deux fois plus mauvais que le tien. J'ai réfléchi à la raison et j'ai corrigé deux lignes pour qu'un tiers des éléments soit supprimé au lieu de 0,1%.

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

C'est comme ça que ça s'est passé :

2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variant Pastushak : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 108521 microsecondes
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variant Korotky : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 5525 microsecondes
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variant Fedoseev : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 4879 microsecondes
2018.11.13 19:45:22.164 Del (GBPUSD.m,H1) variant Semko : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 14479 microsecondes
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variant Pavlov : Somme de contrôle = 998744 ; éléments - 667421 ; temps d'exécution = 0 microsecondes
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variant Nikitin : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 5759 microsecondes
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Vladimir : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 1542 microsecondes

La variante de Pavlov comportait une erreur, j'ai dû la commenter.

Conclusion : calculer des adresses dans un tableau avec une distance arbitraire entre leurs numéros est toujours pire que de traiter des éléments dans une rangée, à une étape donnée, et encore moins à l'étape 1, le compilateur peut l'optimiser.

P.S. Les compilateurs Pascal et Delphi de Borland font en sorte qu'au moment de l'exécution, la variable de la boucle n'a pas d'importance (en mémoire), elle est placée quelque part dans les registres du CPU.

 
Vladimir:

Oui, désolé, une seule fois en effet. J'espérais que quelqu'un serait intéressé par l'approche SGBD et vérifierait, je n'ai pas attendu. J'ai dû le faire moi-même.

J'ai inséré ArrayDeleteValue.mq5 dans ton vérificateur, il est deux fois plus mauvais que le tien. J'ai réfléchi à la raison et j'ai corrigé deux lignes pour qu'un tiers des éléments soient supprimés au lieu de 0,1%.

C'est comme ça que ça s'est passé :

2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variant Pastushak : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 108521 microsecondes
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variant Korotky : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 5525 microsecondes
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variant Fedoseev : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 4879 microsecondes
2018.11.13 19:45:22.164 Del (GBPUSD.m,H1) variant Semko : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 14479 microsecondes
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variant Pavlov : Somme de contrôle = 998744 ; éléments - 667421 ; temps d'exécution = 0 microsecondes
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variant Nikitin : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 5759 microsecondes
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Vladimir : Somme de contrôle = 333586 ; éléments - 667421 ; temps d'exécution = 1542 microsecondes

La variante de Pavlov comportait une erreur, j'ai dû la commenter.

Conclusion : calculer des adresses dans un tableau avec une distance arbitraire entre leurs numéros est toujours pire que de traiter des éléments dans une rangée à une étape donnée, d'autant plus à l'étape 1, le compilateur peut l'optimiser.

P.S. Les compilateurs Pascal et Delphi de Borland font en sorte qu'au moment de l'exécution, la variable de la boucle n'a pas d'importance (en mémoire), elle est placée quelque part dans les registres du CPU.

La version de Pavlov a été corrigée.
Vos valeurs sont étranges. Peut-être avez-vous exécuté le script après le profilage ou le débogueur sans recompiler le code ?
C'est comme ça que ça marche pour moi :

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 микросекунд

Et dans votre version, il génère une somme de contrôle incorrecte. Et la création d'un tableau supplémentaire n'est d'aucune utilité, au contraire, elle ralentit le processus et consomme des ressources supplémentaires.

Dossiers :
 
Par essence, tous les algorithmes sont les mêmes. Tout le monde modifie le tableau élément par élément, et tout le monde s'efforce d'obtenir la variante de Fedoseev, car elle ne comporte rien d'inutile.
Seulement dans mon cas, il est fait en blocs en utilisant ArrayCopy, donc il y a un avantage de vitesse.