Looking for a better way

Post Reply
Thunderbolt4x
Posts: 3
Joined: Thu Nov 17, 2022 8:37 am

Looking for a better way

Post by Thunderbolt4x »

Hi,

I am trying to find a better way to change the class field that I am sorting an array of classes by. In my test script I am testing two methods, one is to copy a selected field to the Key field and then sort the array on the Key field. The second test is to use a switch statement in the Compare function and have different code for each field that could be sorted by.

The first way has the additional overhead of copying the data from one field to the other for all records. The second way means that I have to add code for every field in the class. Adding the extra code isn’t a big deal but I am trying to find a way that is more generic.

Does anyone have a better alternative to sorting the array than what I have? I was wondering if I could do something with templates or polymorphism.

Attached is the test script.

Thanks in advance.

Code: Select all

// TestSort.mq4

#property strict
#include <Arrays/ArrayObj.mqh>

// These defines are in Empty4 but not MT5. Define them for cross platform compatibility
#define MODE_ASCEND 0
#define MODE_DESCEND 1

CArrayObj SymbolTable;

int SortColumn = 0;

class CSymbolRecord : public CObject
{

public:
    string  Key;
    string  Name;
    double  Price;
    int     Sequence;
    datetime StartDate;

    virtual int Compare(const CObject *node, const int mode=0) const
    {
        if (mode<=0) return(0);

        CSymbolRecord *record = (CSymbolRecord*)node;

        int result=0;

        switch(SortColumn)
        {
        case 0:
	        if(record.Key==this.Key) return(0);
	        result = ((this.Key>record.Key)*2)-1;
            break;	    
        case 1:
	        if(record.Name==this.Name) return(0);
	        result = ((this.Name>record.Name)*2)-1;
            break;	    
        case 2:
	        if(record.Price==this.Price) return(0);
	        result = ((this.Price>record.Price)*2)-1;
            break;	    
        case 3:
	        if(record.Sequence==this.Sequence) return(0);
	        result = ((this.Sequence>record.Sequence)*2)-1;
            break;	    
        case 4:
	        if(record.StartDate==this.StartDate) return(0);
	        result = ((this.StartDate>record.StartDate)*2)-1;
            break;	    
        }
        
	    if (mode==2) result *= -1;

        return result;
    }
};


void OnStart() 
{
    SortColumn = 3;
    
    AddRecord("NZDUSD", 1.23456, 2, D'2023.02.12');
    AddRecord("EURUSD", 24.85, 1, D'2023.11.08');
    AddRecord("AUDUSD", 18.21, 11 ,D'2022.04.15');
    AddRecord("GBPUSD", 4.63, 8, D'2023.12.02');

    // Uncomment out the next line when testing copying test field contents to Key
//    if(SortColumn==0) CopyToKey(3);

    SymbolTable.Sort(MODE_DESCEND);
    PrintRecords();
}


void CopyToKey(int fieldNumber)
{
    for(int i=0; i<SymbolTable.Total(); i++)
    {
        CSymbolRecord *record = SymbolTable.At(i);
        
        if(fieldNumber==0) record.Key=record.Name;    
        if(fieldNumber==1) record.Key=DoubleToString(record.Price, 5);    
        if(fieldNumber==2) record.Key=IntegerToString(record.Sequence);    
        if(fieldNumber==3) record.Key=TimeToString(record.StartDate);    
    }
}


void PrintRecords()
{
    for(int i=0; i<SymbolTable.Total(); i++)
    {
        CSymbolRecord *record = SymbolTable.At(i);

        Print(record.Name+"    "+DoubleToString(record.Price, 5)+"     "+IntegerToString(record.Sequence)+"   "+record.StartDate );
    }
}


void AddRecord(string name, double price, int sequence, datetime startDate)
{
    CSymbolRecord *record = new CSymbolRecord();

    record.Key = name;
    record.Name = name;
    record.Price = price;
    record.Sequence = sequence;
    record.StartDate = startDate;
    SymbolTable.Add(record);
}
Post Reply

Return to “Coders Hangout”