Features of the mql5 language, subtleties and tricks - page 134

 
Easy sorting of an array of structures
#property strict

// Сортировка массива структур и указателей на объекты по (под-) полю/методу.
#define  ArraySortStruct(ARRAY, FIELD)                                            \
{                                                                                \
  class SORT                                                                     \
  {                                                                              \
  private:                                                                       \
    template <typename T>                                                        \
    static void Swap( T &Array[], const int i, const int j )                     \
    {                                                                            \
      const T Temp = Array[i];                                                   \
                                                                                 \
      Array[i] = Array[j];                                                       \
      Array[j] = Temp;                                                           \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static int Partition( T &Array[], const int Start, const int End )           \
    {                                                                            \
      int Marker = Start;                                                        \
                                                                                 \          
      for (int i = Start; i <= End; i++)                                         \
        if (Array[i].##FIELD <= Array[End].##FIELD)                              \
        {                                                                        \
          SORT::Swap(Array, i, Marker);                                          \
                                                                                 \
          Marker++;                                                              \
        }                                                                        \
                                                                                 \
       return(Marker - 1);                                                       \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static void QuickSort( T &Array[], const int Start, const int End )          \
    {                                                                            \
      if (Start < End)                                                           \
      {                                                                          \
        const int Pivot = Partition(Array, Start, End);                          \
                                                                                 \
        SORT::QuickSort(Array, Start, Pivot - 1);                                \
        SORT::QuickSort(Array, Pivot + 1, End);                                  \
      }                                                                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
  public:                                                                        \
    template <typename T>                                                        \ 
    static void Sort( T &Array[], int Count = WHOLE_ARRAY, const int Start = 0 ) \
    {                                                                            \
      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array);                                              \
                                                                                 \
      SORT::QuickSort(Array, Start, Start + Count - 1);                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
  };                                                                             \
                                                                                 \
  SORT::Sort(ARRAY);                                                             \
}


Application

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(Rates, open);
  ArrayPrint(Rates);

  Print("\nСортируем по high-цене.");
  ArraySortStruct(Rates, high);
  ArrayPrint(Rates);

  Print("\nСортируем по времени.");
  ArraySortStruct(Rates, time);
  ArrayPrint(Rates);
}


Result

Бары без сортировки - как получили.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[1] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0
[2] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[3] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[4] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0

Сортируем по open-цене.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[1] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[2] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0
[3] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[4] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0

Сортируем по high-цене.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[1] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[2] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0
[3] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[4] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0

Сортируем по времени.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[1] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0
[2] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[3] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[4] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0
 
fxsaber:
Handy sorting an array of structures


      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array) - Start; 

Yellow highlighted the missing things, and it seems to me that it's better in order of arguments, first Start, and then Count.

By the way, it is probably more reasonable to sort arrays of structures by indexes (I mean rearrange indexes, not structures themselves), but it depends on the size of the structure, of course.

 
Alexey Navoykov:

I highlighted in yellow what was missing.

Thanks, I missed it.

I think it's better to start with Start and then Count in order of arguments.

The signal is borrowed from MT4-ArraySort.

By the way, it would probably be more reasonable to sort arrays of structures by indexes (I mean rearrange indexes, not structures themselves).

This was the first thing that came to mind, but I gave it up. Because it requires using ArrayCopy of the initial array and the array of indexes. And this is additional memory. And the machine cannot afford such sorting of an array, for example, of millions of MqlTick-elements.

We could have included two sorting variants, but I haven't done it in the source code. In the demonstration, perhaps, the most valuable thing is usability and method of implementation. After studying it, it is already clear how to add to your needs and make an analogue for other functions of arrays with structures (ArrayMaximum, etc.).

ArraySort - Операции с массивами - Справочник MQL4
ArraySort - Операции с массивами - Справочник MQL4
  • docs.mql4.com
//| Script program start function                                    |
 
fxsaber:
Handy sorting an array of structures


Application


Result

How to convert this code to a simple class without using #define ?

 
Vladimir Pastushak:

How to convert this code to a simple class without using #define ?

You can't. ArraySortStruct is supposed to be used as a function without getting into how it is organized.

Just throw in some enludnik its source code and forget about it. After that a really handy for any beginner (and not only) "function" is always at hand.

 
Folks, throw in a reference if there is such, need the flag of time of opening of evening (additional) trading session on FORTS MOEX, and like all looked through but did not find, do not want to write a crutch definition at 19:00 or 19:05 will open trading session
 

A random number from 0 to max with equal probability:

uint get_rand(uint max)
{
   static bool f = false;
   if ( ! f ) {
      f = true;
      srand(GetTickCount());
   }  
   uint limit = (max+1) * ((32767+1) / (max+1));
   uint val;
   while ((val = rand()) >= limit);
   return val % (max+1);
}
 
Renat Fatkhullin:

The multi-buffer is great for speeding up the editor and is safe.

It does not write anything to disk and only keeps data in memory.

at what rating will I be able to insert a picture on the website?
 
Vict:

A random number from 0 to max with equal probability:

Your function is 100% equivalent:

uint get_rand(uint max)
  {
   static bool f = true;
   if (f) {f = ~f; srand(GetTickCount());} 
   return rand() % (max+1);
  }

because, firstly.

uint limit = (max+1) * (32767+1 / (max+1));

simplifies to

uint limit = (max+1) * 32767+1; // т.е. при даже max=0 limit =32768

therefore, secondly

while ((val = rand()) >= limit);

is always performed once.

Complexity is a detailed statement of simplicity. ))

 
Nikolai Semko:

Your function is 100% equivalent:

because, firstly.

simplifies to

therefore, secondly

is always performed once.

Complexity is a detailed statement of simplicity. ))

You are very considerate, thank you. I made a mistake, didn't put brackets, so I would use "unfair" function.

SZZ: made corrections to the original post.

Reason: