Borrar una matriz de elementos definidos - página 8

 
No sé qué es mt4, ni siquiera se ejecuta en win10, creo que eso es algo bueno
 
Maxim Dmitrievsky:
No sé qué es mt4, ni siquiera se ejecuta en win10, creo que eso es algo bueno
Bien dicho:)
 

He ajustado la matriz.

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

Tuve que usar ArrayCopy , porqueMQL5 juraba que el array era estático.


 
Nikolai Semko:

Si es un concurso de velocidad, ofreceré mi propia variante...

Su variante es efectivamente la más rápida, pero contiene un error: si todos los elementos de un array son iguales a un filtro, su función saldrá del array.

Voy a ofrecer mi propia variante, es un poco más lenta que la tuya:

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:

Lleva varios años haciendo este tipo de preguntas. ¿Has aprendido mucho? Lo siento, pero es obvio que todavía estás en el nivel de los bytes y las matrices elementales.

La propia pregunta está formulada de forma incorrecta. La tarea no consiste en eliminar los valores duplicados (tarea de nivel CME) sino en algo mucho mayor, debe actualizar la lista de elementos válidos. Si es así, la pregunta debería sonar completamente diferente. Confundes y engañas a los participantes y, en primer lugar, a ti mismo: impones a los participantes una solución equivocada en principio y pides que la hagan efectiva.

No programo por programar, no tengo el objetivo de convertirme en un megaprogramador ni de ser inteligente en los foros.

¿Qué es lo que no entiendes en la pregunta: Borrar un array de elementos definidos?

 
Sergey Pavlov:

Su variante es efectivamente la más rápida, pero contiene un error: si todos los elementos de un array son iguales a un filtro, su función saldrá del array.

Te propongo mi variante, es un poco más lenta que la tuya:


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

Sí, gracias. Corregido.

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

Sólo que también tienes un error en alguna parte, porque la suma de comprobación no coincide porque falta un elemento en alguna parte. No se sabe dónde.

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

Lo he retocado eliminando pasajes innecesarios

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:
En ambos casos, cada elemento se arrastra como máximo una vez.

Sí, lo siento, una vez en efecto. Esperaba que alguien se interesara por el enfoque del DBMS y lo comprobara, no esperé. Tuve que hacerlo yo mismo.

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

Insertado ArrayDeleteValue.mq5 en tu comprobador, es el doble de malo que el tuyo. He pensado en la razón y he arreglado dos líneas para que se elimine un tercio de los elementos en lugar del 0,1%.

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

Así es como resultó:

2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variante Pastushak: Checksum = 333586; elementos - 667421; tiempo de ejecución = 108521 microsegundos
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variante Korotky: Checksum = 333586; elementos - 667421; tiempo de ejecución = 5525 microsegundos
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variante Fedoseev: Checksum = 333586; elementos - 667421; tiempo de ejecución = 4879 microsegundos
2018.11.13 19:45:22.164 Del (GBPUSD.m,H1) variante Semko: Checksum = 333586; elementos - 667421; tiempo de ejecución = 14479 microsegundos
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Pavlov: Checksum = 998744; elementos - 667421; tiempo de ejecución = 0 microsegundos
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Nikitin: Checksum = 333586; elementos - 667421; tiempo de ejecución = 5759 microsegundos
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Vladimir: Checksum = 333586; elementos - 667421; tiempo de ejecución = 1542 microsegundos

La variante de Pavlov tenía un error, tuve que comentarlo.

Conclusión: calcular direcciones en un array con una distancia arbitraria entre sus números sigue siendo peor que procesar elementos en una fila, en un paso dado, y mucho menos en el paso 1, el compilador puede optimizarlo.

P.D. Los compiladores Pascal y Delphi de Borland hacen que en tiempo de ejecución la variable de bucle no importe (en memoria), se pone en algún lugar de los registros de la CPU.

 
Vladimir:

Sí, lo siento, una vez en efecto. Esperaba que alguien se interesara por el enfoque del DBMS y lo comprobara, no esperé. Tuve que hacerlo yo mismo.

Insertado ArrayDeleteValue.mq5 en tu comprobador, es el doble de malo que el tuyo. He pensado en las razones y he arreglado dos líneas para que se elimine un tercio de los elementos en lugar del 0,1%.

Así es como resultó:

2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variante Pastushak: Checksum = 333586; elementos - 667421; tiempo de ejecución = 108521 microsegundos
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variante Korotky: Checksum = 333586; elementos - 667421; tiempo de ejecución = 5525 microsegundos
2018.11.13 19:45:22.148 Del (GBPUSD.m,H1) variante Fedoseev: Checksum = 333586; elementos - 667421; tiempo de ejecución = 4879 microsegundos
2018.11.13 19:45:22.164 Del (GBPUSD.m,H1) variante Semko: Checksum = 333586; elementos - 667421; tiempo de ejecución = 14479 microsegundos
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Pavlov: Checksum = 998744; elementos - 667421; tiempo de ejecución = 0 microsegundos
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Nikitin: Checksum = 333586; elementos - 667421; tiempo de ejecución = 5759 microsegundos
2018.11.13 19:45:22.179 Del (GBPUSD.m,H1) variante Vladimir: Checksum = 333586; elementos - 667421; tiempo de ejecución = 1542 microsegundos

La variante de Pavlov tenía un error, tuve que comentarlo.

Conclusión: calcular direcciones en un array con una distancia arbitraria entre sus números sigue siendo peor que procesar elementos en una fila en un paso determinado, más aún en el paso 1, el compilador puede optimizarlo.

P.D. Los compiladores Pascal y Delphi de Borland hacen que en tiempo de ejecución la variable de bucle no importe (en memoria), se pone en algún lugar de los registros de la CPU.

La versión de Pavlov ha sido corregida.
Sus valores son extraños. ¿Quizás has ejecutado el script después de perfilar o depurar sin recompilar el código?
Así es como funciona para mí:

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

Y en su versión genera una suma de comprobación incorrecta. Y la creación de un array adicional no tiene ningún beneficio, al contrario, ralentiza el proceso y consume recursos adicionales.

Archivos adjuntos:
 
En esencia, todos los algoritmos son iguales. Todos modifican la matriz elemento por elemento, y todos se esfuerzan por la variante Fedoseev, porque no tiene nada innecesario.
Sólo que en mi caso se hace en bloques usando ArrayCopy, por lo que hay una ventaja de velocidad.
Razón de la queja: