Очистка массива от заданного (ых) элементов - страница 11

 
Nikolai Semko:

Браво! После исправления пары ошибок Вы меня сбросили с пьедестала даже без применения ArrayCopy. Шах и Мат. :)) 

Стоит наверно поменять
for(;;)

на

while(true)

Все равно выход через break

P.S. Ради интереса прогнал прямое копирование по всему массиву.
template<typename T>
int arrayFilter(T &data[],const T value)
  {
     int s, _s = s = ArraySize(data);
     bool result = false;
     
     for(int i=0, j=0; i<_s; i++)
     {
          if( data[i] == value )
          {
               result = true;
               s--;
               continue;
          }
          if( result )
               data[j] = data[i];
          j++;
     }
     
     if(s < _s)
          ArrayResize(data, s);
     
     return s;
  }
 
Konstantin Nikitin:
Стоит наверно поменять

на

Все равно выход через break

Без разницы. Из бесконечных циклов мне for больше нравиться, т.к. короче и true не сбивает с толку новичков.
 
Камень в огород разработчиков оптимизатора МТ5/ME (builds 1945).
Terminal Windows 10 (build 17134) x64, IE 11, UAC, Intel Core i7-7700HQ  @ 2.80GHz, Memory: 5276 / 16250 Mb


Почему код:
arr[j++] = arr[i];

Работает медленнее чем:
arr[j] = arr[i];
j++;



Если брать участие в этом состязании без правил, то копируем код "лидера" (на данный момент это Kuznetsov) и изменяем его в соответствии с вышеописанным поведением системы.
Получаем стабильный выигрыш порядка 20 мс от изначальных 740 мс времени выполнения:

template <typename T>
int arrayFilter_ALXIMIKS(T &arr[], const T x)  // вариант ALXIMIKS
{
        int i=0;
        int j=ArraySize(arr)-1;
        for(;;) {
                while(arr[i]!=x && i<j) i++;
                while(arr[j]==x && i<j) j--;
                if (i<j) {
                        arr[i]=arr[j];
                        i++;
                        j--;
                } else break;
        }
        ArrayResize(arr,j);
        return j;
}
 

Кстати любопытно как изменятся результаты, если исходный массив будет как серия. ArraySetAsSeries(arr,true)

 
Sergey Dzyublik:
Если брать участие в этом состязании без правил, то копируем код "лидера" (на данный момент это Kuznetsov) и изменяем его в соответствии с вышеописанным поведением системы.

Получаем стабильный выигрыш порядка 20 мс от изначальных 740 мс времени выполнения:

Стоит добавить. Если не важна последовательность элементов массива. То да, вариант отличный. Если важно сохранить последовательность, то нужно что-то другое.

 

Раз пошла такая пьянка, вот мой вариант:

int SokolovDelRetry(int &array[], const int val)
{
   int total = ArraySize(array);
   int in = -1, count = 0, diff = 0;
   for(int i = 0; i < total; i++)
   {
      diff++;
      if(array[i] == val)
      {
         diff--;
         if(in != -1)
         {
            if(diff>0)
            {
               ArrayCopy(array, array, in, i-diff, diff);
               in = in + diff;
               diff = 0;
            }
            count++;
         }
         else
         {
            in = i;
            diff = 0;
            count++;
         }
      }
   }
   if(diff > 0)
      ArrayCopy(array, array, in, total - diff, diff);
   ArrayResize(array, total - count);
   return total - count;
}

results:

2018.11.14 16:20:15.293 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Pastushak: Контрольная сумма = 495345526; элементов - 998956; время выполнения = 89383 микросекунд
2018.11.14 16:20:15.313 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Korotky:   Контрольная сумма = 495345526; элементов - 998956; время выполнения = 18148 микросекунд
2018.11.14 16:20:15.337 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Fedoseev:  Контрольная сумма = 495345526; элементов - 998956; время выполнения = 15637 микросекунд
2018.11.14 16:20:15.347 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Semko:     Контрольная сумма = 495345526; элементов - 998956; время выполнения = 4626 микросекунд
2018.11.14 16:20:15.367 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Pavlov:    Контрольная сумма = 495345526; элементов - 998956; время выполнения = 16976 микросекунд
2018.11.14 16:20:15.407 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Nikitin:   Контрольная сумма = 495345526; элементов - 997945; время выполнения = 27381 микросекунд
2018.11.14 16:20:15.427 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Vladimir:  Контрольная сумма = 495345526; элементов - 998956; время выполнения = 16178 микросекунд
2018.11.14 16:20:15.457 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Peter:     Контрольная сумма = 495345526; элементов - 998956; время выполнения = 19618 микросекунд
2018.11.14 16:20:15.477 ArrayDeleteValue__6 (FORTS-USDRUB,H1)   вариант Sokolov:  Контрольная сумма = 495345526; элементов - 998956; время выполнения = 11058 микросекунд

З.ы. В принципе предел скорости достигнут. Дальше только микрооптимизации и шаманство с циклом for:

Думаю результат Николая это умелое использовал таких микрооптимизаций.

Файлы:
 
Vladimir Pastushak:

Есть массив содержащий набор данных по типу 1,2,3,6,9,5,6,3,25,6,8,7,4 нужно удалить например значения 3 и на выходе получить тот же массив без 3 и пустых мест...

Я ищу самый быстрый способ очистки массива от ненужных значений...

На ум приходит такой пример

Может есть способы экономнее и быстрее ?

Владимир, а зачем такое нужно?
Как я понимаю, такое необходимо проделывать с индикаторным буфером. Но тогда разве не логичнее пустые и (или) "лишние" значения заменять предыдущим значением или, к примеру, средним арифметическим крайних значений? Тогда это будет выполняться гораздо быстрее и размерность массива останется та же. 

 
Nikolai Semko:

Владимир, а зачем такое нужно?
Как я понимаю, такое необходимо проделывать с индикаторным буфером. Но тогда разве не логичнее пустые и (или) "лишние" значения заменять предыдущим значением или, к примеру, средним арифметическим крайних значений? Тогда это будет выполняться гораздо быстрее и размерность массива останется та же. 

Это нужно для вывода информации, большого объема информации и на основе ее делать дальнейшие расчеты. Функция такого рода нужна что бы очищать массив от неактуальных данных. И самое главное что она должна работать очень быстро! Мой аналог по скорости уступает всем, это вызывает фризы при отображении информации. 

 
Nikolai Semko:

Владимир, а зачем такое нужно?
Как я понимаю, такое необходимо проделывать с индикаторным буфером. Но тогда разве не логичнее пустые и (или) "лишние" значения заменять предыдущим значением или, к примеру, средним арифметическим крайних значений? Тогда это будет выполняться гораздо быстрее и размерность массива останется та же. 

Когда предусмотрена работа нескольких советников с большим количеством открытых позиций\ордеров в mql4 на мой взгляд проще держать массив с тикетами и контролировать закрылся-ли ордер перебирая этот массив, вместо перебора всех открытых с проверкой символа и магика. Так вот если ордер закрылся, то его надо из массива "вычеркнуть". В таких случаях я пользовался копированием массива "сам в себя" и сокращением размерности на единицу. Что и предложил  Vasiliy Sokolov, за что большое спасибо, буду знать что это не самый тяжёлый вариант, так как я никогда не задумывался о скорости. Почему задача была поставлена удалить несколько равных элементов вопрос ещё тот...

ps пока я писал, ответ уже есть. Выходит что и вопрос уже не тот...))))))
 
Alexey Viktorov:

Когда предусмотрена работа нескольких советников с большим количеством открытых позиций\ордеров в mql4 на мой взгляд проще держать массив с тикетами и контролировать закрылся-ли ордер перебирая этот массив, вместо перебора всех открытых с проверкой символа и магика. Так вот если ордер закрылся, то его надо из массива "вычеркнуть". В таких случаях я пользовался копированием массива "сам в себя" и сокращением размерности на единицу. Что и предложил  Vasiliy Sokolov, за что большое спасибо, буду знать что это не самый тяжёлый вариант, так как я никогда не задумывался о скорости. Почему задача была поставлена удалить несколько равных элементов вопрос ещё тот...

ps пока я писал, ответ уже есть. Выходит что и вопрос уже не тот...))))))

тогда примерно понял.

если массив ордеров, то последовательность не важна, поэтому целесообразней использовать вариант Кузнецова с заполнением "дырок" значениями из верхней части массива, чтобы не двигать остальные элементы массива. Так конечно же быстрее.