Function - Method for sorting an array of structures. Prize 10$

 

Hi all, there is a function written by 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);                                          \
}                                  


Works without problems in MT 5, but in MT 4 it complains aboutArraySwap because Mql 4 doesn't support it...


Maybe someone has some variants of universal sorting array structures working in MT 5 and MT 4 ?


I can still offer a reward for the fastest implementation of 10$

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

You need to write your structure as a class that inherits from CObject and write your Compare method, then use CArrayObj. This will be the fastest option.

And about ArraySwap here - https://www.mql5.com/ru/docs/array/arrayswap should not be difficult to write such function for MT4.

 
Dmitry Fedoseev:

You need to write your structure as a class that inherits from CObject and write your Compare method, then use CArrayObj. This will be the fastest option.

And about ArraySwap here - https://www.mql5.com/ru/docs/array/arrayswap should not be difficult to write such function for MT4.

I read this information.

We are talking about an array of structures, not a simple array.

 
Vladimir Pastushak:

I have read this information.

We're talking about an array of structures, not a simple array.

IsCArrayObj a simple array?

 
Dmitry Fedoseev:

Is CArrayObj a simple array?

No, I don't have a friendly relationship with OOP.

 

@fxsaber's variant will be the fastest, because the compiler will deploy macros in full code

To avoid code duplication, wrap necessary sortings by required fields in functions and use


variants with inheritance fromCObject will be many times slower, you will have to add the corresponding Compare methods

 
Igor Makanu:

@fxsaber's variant will be the fastest, because the compiler will deploy macros in full code

To avoid code duplication, wrap necessary sortings by required fields in functions and use


and the variants withCObject inheritance will be many times slower, besides you will have to add the corresponding Compare methods

There we copy data from one array to another and then shuffle the indexes. Maybe it will be faster using ArraySort().

 

And here's an option - modify the function to suit your structure:

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

But with 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:

But this variant - to change the function to fit your structure:

is not an option at all - this is a common solution to a particular problem, portability of such solutions for later use will be commensurate with writing from scratch )))

The code in the first post is implemented by copying, if the task is to perform sorting in 2 or 3 places

or, as I suggested above, if you are going to use sorting by different fields in different code sections, it would be better to create wrapper functions for the suggested macros


HH: The sources of C# with all base classes on Microsoft site, there are sorts, and they are similar to interfaces in SB, but alas, they didn't finalize SB - they said do it yourself ;)

 
Igor Makanu:

not an option at all - this is a common solution to a particular problem, portability of such solutions for later use will be comparable to writing from scratch )))

The code in the first post may be implemented by copying if the task is to perform sorting in 2 or 3 code fragments

or, as I suggested above, if you are going to use sorting by different fields in different code sections, it would be better to create wrapper functions for the suggested macros


HH: The sources of C# with all basic classes on Microsoft site, there are sorts, and they are similar to interfaces in SB, but alas, they didn't finalize SB - they said do it yourself ;)

Change the variable type in one place and the compiler will show errors in the other three - change the field name. You would think that dozens of structures need to be sorted somewhere. Yes, most likely one structure requires sorting.

Reason: