Array sorted by decreasing time

 

Hi, 

How can I sort some array by decreasing time.

So, for example, always the position 0 will be the last data received, position 1 will be the second last, and so on.

I Have some code example but it is stucked on the part that I need to sort the array.

double ex_array[6]; 
int count=0;
datetime new_bar=0;

void FillArray()
  {
   datetime lastbar_time=SeriesInfoInteger(Symbol(),PERIOD_M1,SERIES_LASTBAR_DATE);
   
   if(count==6)
      count=0;
   
   if(lastbar_time > new_bar)
     {
      double value = iClose(_Symbol,PERIOD_M5,0) * iVolume(_Symbol,PERIOD_M5,0); // Getting the value
      ex_array[count]=value;  // Filling the array
      count++; //Counting next array position
      new_bar=lastbar_time;
     }
   
  }


So, instead of everytime search wich the array position is the last data received, I would like to know how can I sort the array that everytime the array receive a new data, it will be the position 0, and the second last will be the position 1 and so on.

 
You do this with ArraySetAsSeries.

You turn off AsSeries, you resize the array, add your new value and turn it back on.

I personally like to use FiFo and FiLo buffers to organize my data. Sometimes a chained list or a map is useful.

I shoud add my buffer classes can be accessed like an array for reading. That was very helpful.
 
Dominik Egert #:
You do this with ArraySetAsSeries.

You turn off AsSeries, you resize the array, add your new value and turn it back on.

I personally like to use FiFo and FiLo buffers to organize my data. Sometimes a chained list or a map is useful.

I shoud add my buffer classes can be accessed like an array for reading. That was very helpful.

Thanks for your answer.
But it is not working for me. 

 

I think I found a solution. 

It seem to working.

If anyone knows a better or a fast solution, please help me!


double ex_array[6]; 
double temp_array[6];
datetime new_bar=0;

void FillArray()
     {
      datetime lastbar_time=(datetime)SeriesInfoInteger(Symbol(),PERIOD_M1,SERIES_LASTBAR_DATE);
     
      if(lastbar_time > new_bar)
        {
         double value = iClose(_Symbol,PERIOD_M1,0); // Getting the value
         ArrayCopy(temp_array,ex_array,1,0,5);
         temp_array[0]=value;  // Filling the array
         ArrayCopy(ex_array,temp_array,0,0,6);
         new_bar=lastbar_time;
         
         ArrayPrint(ex_array);
        }
      
     }
 
Guilherme Mendonca #: If anyone knows a better or a fast solution, please help me!

You were already given a fast solution by Dominik

Indicators have buffers which automatically shift. Arrays do not automatically do anything. You must do it in EA.
          Array indexing and resizing an AS_SERIES array - MQL4 programming forum #2 (2017)

 
You could also simply use the array as intended in any language. Grow at the end, use the size of the array as reference, deduct one from the size and always have the most recent value as the last element. 
BTW, that's how the terminal does it as well. OR you go the noob way and keep copying data around.
This might work for such a small array, but once the array has considerable size, you will get performance issues.
What you have shown as solution is for sure the most expensive way to do it.


You use double the amount of mem needed for the task, you don't sort, you just push bits around with no sense to what you are trying to achieve.

Well, if it serves your needs, do it like you showed.


 
Dominik Egert #:
You could also simply use the array as intended in any language. Grow at the end, use the size of the array as reference, deduct one from the size and always have the most recent value as the last element. 
BTW, that's how the terminal does it as well. OR you go the noob way and keep copying data around.
This might work for such a small array, but once the array has considerable size, you will get performance issues.
What you have shown as solution is for sure the most expensive way to do it.


You use double the amount of mem needed for the task, you don't sort, you just push bits around with no sense to what you are trying to achieve.

Well, if it serves your needs, do it like you showed.


Ok Dominik, but I tried your solution and did not worked.

I think I did not get your code idea.

if is it possible, could you give us a code example?

Tks

 

OK, i will show an example.


double arr[];

// Add new value
int size = ArrayResize(arr, ArraySize(arr) + 1);
arr[size - 1] = 123;


// Now lets do this on a AsSeriesArray

// First turn off AsSeries
const bool is_series = ArrayGetAsSeries(arr);

ArraySetAsSeries(arr, !is_series);
size = ArrayResize(arr, ArraySize(arr) + 1);

// Add new value
arr[size - 1] = 234;

// Turn AsSeries back on
ArraySetAsSeries(arr, is_series);


// And here as a function template
template <typename T>
int add_element_to_array(T& array[], const T new_value)
{
        // Get state
        const bool is_series = ArrayGetAsSeries(array);

        // Resize, add, revert state
        ArraySetAsSeries(array, !is_series);
        const int size = ArrayResize(array, ArraySize(array) + 1);
        array[size-1] = new_value;
        ArraySetAsSeries(array, is_series);

        // Return
        return(size);
}


I am questioning, why this was so hard....

 
Dominik Egert #:

OK, i will show an example.



I am questioning, why this was so hard....


Now I got your idea.
You are increasing 1 element at the end of the array.
But, in fact I'm working with a fixed size array.

Thanks anyway.
 

 
Yes, I noticed.

You could use a "current" pointer, pointing to the current/most recent entry.

You could use a "circle-buffer" if you want to overwrite the oldest element and always only keep the most recent x elements.

I circle buffer is a FiFo buffer with a fixed max length.


 

I've been using this some time ago, for fixed size arrays. 

void ShiftBuffer(double &arr[], int shift=1)
  {
   int count=ArraySize(arr)-shift;
   if(shift>0 && count>0)
     {
      ArrayCopy(arr,arr,shift,0,count);
     }
  }
Reason: