Функция - Метод сортировки массива структур. Приз 10$

 

Всем привет, есть функция написанная fxsaber

template <typename T>                                       
void ArrayReindex( T &Array[], const double &TmpSort[][2] )
{                         
  T TmpArray[];
  
  for (int x = ::ArrayResize(TmpArray, ::ArrayRange(TmpSort, 0)) - 1; x >= 0; x--)
    TmpArray[x] = Array[(int)(TmpSort[x][1] + 0.1)];
    
  ::ArraySwap(Array, TmpArray);
              
  return;     
}             

// Сортировка массива структур и указателей на объекты по (под-) полю/методу.
#define ArraySortStruct(ARRAY, FIELD)                                      \
{                                                                          \
  double TmpSort[][2];                                                     \
                                                                           \
  for (int x =::ArrayResize(TmpSort, ::ArraySize(ARRAY)) - 1; x >= 0; x--) \
  {                                                                        \
    TmpSort[x][0] = (double)ARRAY[x].FIELD;                                \
    TmpSort[x][1] = x;                                                     \
  }                                                                        \
                                                                           \
  ::ArraySort(TmpSort);                                                    \
  ::ArrayReindex(ARRAY, TmpSort);                                          \
}                                  


В MT 5 работает без проблем в МТ 4 ругается на ArraySwap   так как Mql 4 ее не поддерживает...


Может у кого то есть варианты универсальной сортировки массива структур работающий и в мт 5 и в мт 4 ?


Могу еще предложить вознаграждение за наиболее быструю реализацию 10$

Документация по MQL5: Операции с массивами / ArraySort
Документация по MQL5: Операции с массивами / ArraySort
  • www.mql5.com
//| Получение значений границ для тиковых объемов                    | //| Custom indicator initialization function                         | //| Custom indicator iteration function                              | //
 

Нужно писать свою структура как класс наследующий CObject и писать свой метод сравнения Compare, потом использовать CArrayObj. Это будет самый быстрый вариант.  

А про ArraySwap здесь - https://www.mql5.com/ru/docs/array/arrayswap не должно быть сложно написать такую функцию для МТ4.

 
Dmitry Fedoseev:

Нужно писать свою структура как класс наследующий CObject и писать свой метод сравнения Compare, потом использовать CArrayObj. Это будет самый быстрый вариант.  

А про ArraySwap здесь - https://www.mql5.com/ru/docs/array/arrayswap не должно быть сложно написать такую функцию для МТ4.

Я читал эту информацию. 

Речь идет о массиве структур а не о простом массиве.

 
Vladimir Pastushak:

Я читал эту информацию. 

Речь идет о массиве структур а не о простом массиве.

А CArrayObj это простой массив?

 
Dmitry Fedoseev:

А CArrayObj это простой массив?

Нет, у меня не сложилось с ООП дружеских отношений.

 

вариант от @fxsaber будет самым быстрым, т.к. компилятор развернет макроподстановки в полный код

чтобы не было дублирования кода оберните необходимые сортировки по необходимым полям в функции и пользуйтесь


а варианты с наследованием от CObject будут в разы  медленнее, да и будет постоянная необходимость дописывать  соответствующие методы Compare

 
Igor Makanu:

вариант от @fxsaber будет самым быстрым, т.к. компилятор развернет макроподстановки в полный код

чтобы не было дублирования кода оберните необходимые сортировки по необходимым полям в функции и пользуйтесь


а варианты с наследованием от CObject будут в разы  медленнее, да и будет постоянная необходимость дописывать  соответствующие методы Compare

Там копирование данных из одного массива в другой, потом перестановка индексов. Может и быстрее будет за счет использования ArraySort().

 

А вот такой вариант - изменить функцию под свою структуру:

#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

struct SMy{
   int x1;
   int x2;
};

SMy s[3]={{4,44},{2,22},{3,33}};

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(){
   
   SortHoareUp(s);
   
   for(int i=0;i<3;i++){
      Alert(s[i].x1," ",s[i].x2);
   }
   
}


void SortHoareUp(SMy  &aAr[])
  {
   HoareUp(aAr,0,ArraySize(aAr)-1);
  }

void HoareUp(SMy  &aAr[],int aLeft,int aRight)
  {
   SMy tmp;
   int i=aLeft;
   int j=aRight;
   
   int xx=aAr[(aLeft+aRight)/2].x1; // int заменить на тип поля по которому выполняется сравнение
   
   do
     {
   while(i<aRight && aAr[i].x1<xx)i++;
   while(j>aLeft && xx<aAr[j].x1)j--;
   if(i<=j)
     {
      tmp=aAr[i];
      aAr[i]=aAr[j];
      aAr[j]=tmp;
      i++;
      j--;
     }
  }
   while(i<=j);
   if(aLeft<j)HoareUp(aAr,aLeft,j);
   if(i<aRight)HoareUp(aAr,i,aRight);
}
 

А вот с CObjArray

#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

#include <Arrays/ArrayObj.mqh>

class CMyClass:public CObject{
   public:
      int x1;
      int x2;
      int x3;     
      CMyClass(int ax1,int ax2,int ax3){
         x1=ax1;
         x2=ax2;         
         x3=ax3;           
      }
      int Compare(const CObject *node,const int mode=0)const{
         const CMyClass * t=node;
         if(mode==0 && t.x1>this.x1){
            return(1);
         }
         if(mode==1 && t.x1<this.x1){
            return(1);         
         }
         return(-1);
      }      
};

CMyClass * tmp;
CArrayObj a;

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(){

   a.Add(new CMyClass(1,11,111));
   a.Add(new CMyClass(2,22,222));   
   a.Add(new CMyClass(3,33,333));   
   
   Alert("===");
   
   Al(1);
   a.Sort(0);   
   Al(2);
   a.Sort(1);      
   Al(3);

   
  }
//+------------------------------------------------------------------+

void Al(int n){
   Alert("-"+(string)n+"-");
   for(int i=0;i<a.Total();i++){
      tmp=a.At(i);
      Alert(tmp.x1," ",tmp.x2," ",tmp.x3);
   }   
}
 
Dmitry Fedoseev:

А вот такой вариант - изменить функцию под свою структуру:

не вариант вовсе - это обычное решение конкретной задачи, переносимость таких решений  для последующего использования будет соизмерима с написанием с чистого листа )))

код в первом сообщении переносится путем копирования если стоит задача в 2-х - 3-х местах кода выполнить сортировку

или, как я предложил выше, если предполагается частое использование сортировок по разным полям структур в разных участках кода - то оптимальнее сделать функции-обертки для предложенного макроса


ЗЫ: исходники C# со всеми базовыми классами на сайте Майкрософт, там есть сортировки, и они похожи на интерфейсы  в СБ, но увы, не доделали СБ - сказали сами делайте ;)

 
Igor Makanu:

не вариант вовсе - это обычное решение конкретной задачи, переносимость таких решений  для последующего использования будет соизмерима с написанием с чистого листа )))

код в первом сообщении переносится путем копирования если стоит задача в 2-х - 3-х местах кода выполнить сортировку

или, как я предложил выше, если предполагается частое использование сортировок по разным полям структур в разных участках кода - то оптимальнее сделать функции-обертки для предложенного макроса


ЗЫ: исходники C# со всеми базовыми классами на сайте Майкрософт, там есть сортировки, и они похожи на интерфейсы  в СБ, но увы, не доделали СБ - сказали сами делайте ;)

В одном месте тип переменной изменить, а три остальных компилятор ошибками покажет - изменить имя поля. Можно подумать где-то десятки структур требуют сортировки. Да скорее всего одна структура требует сортировки.