関数 - 構造体の配列をソートするためのメソッド。賞金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);                                          \
}                                  


MT5では問題なく動作しますが、MT4ではMql4が対応していないため、ArraySwapについて 文句を言われます...。


もしかしたら、MT5とMT4で動作するユニバーサルソート配列 構造のバリエーションを持っている人がいるかもしれませんね?


最速の実装には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、MT4用のこのような関数を書くことは難しくないはずです。

 
Dmitry Fedoseev:

構造体をCObjectを継承したクラスとしてCompareメソッドを記述し、CArrayObjを使用する必要があります。これが最速の選択肢となる。

また、こちらのArraySwapについてですが、https://www.mql5.com/ru/docs/array/arrayswap、MT4用のこのような関数を書くことは難しくないはずです。

この情報を読みました。

単純な配列ではなく、構造体の配列の話をしているのです。

 
Vladimir Pastushak:

この情報を読みました。

単純な配列ではなく、構造体の配列について話しているのです。

CArrayObjは 単純な配列ですか?

 
Dmitry Fedoseev:

CArrayObjは単純な配列ですか?

いいえ、OOPとは友好的な関係ではありません。

 

コンパイラはマクロをフルコードに展開するので、@fxsaber の 変形が最も速いでしょう。

コードの重複を避けるため、必須フィールドによる必要なソートを関数でラップし、その関数で


CObject を継承したバリアントは何倍も 遅くなり、対応する Compare メソッドを追加する必要があります。

 
Igor Makanu:

コンパイラはマクロをフルコードに展開するので、@fxsaber の 変形が最も速いでしょう。

コードの重複を避けるため、必須フィールドによる必要なソートを関数でラップし、その関数で


CObject 継承の variant は何倍も 遅くなり、さらに対応する 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箇所でソートを行うタスクの場合

あるいは、上で提案したように、異なるコードセクションで異なるフィールドによるソートを使用する場合、提案されたマクロのラッパー関数を作成する方がよいでしょう。


HH: MicrosoftのサイトにあるC#のソースにはすべての基底クラスがあり、それらはSBのインターフェイスに似ています、しかし、残念ながら、彼らはSBを最終化しませんでした - 彼らは自分でやれと言いました;)

 
Igor Makanu:

これは特定の問題に対する一般的な解決策であり、このような解決策を後で使用する場合の移植性は、ゼロから書くことに匹敵します )))

最初の投稿のコードは、2つまたは3つのコードフラグメントでソートを実行するタスクである場合、コピーで実装することができます。

あるいは、上で提案したように、異なるコードセクションで異なるフィールドによるソートを使用する場合、提案されたマクロのラッパー関数を作成する方がよいでしょう。


HH: MicrosoftのサイトにあるC#のソースには、基本的なクラスがすべて揃っていて、SBのインターフェイスに似ています。)

一か所で変数の型を変更すると、コンパイラは他の3か所でエラーを表示します - フィールド名を変更します。何十もの構造物をどこかで仕分けする必要があると思うのでしょう。はい、ほとんどの場合、1つの構造で仕分けが必要です。

理由: