Different Array Number

To add comments, please log in or register
Mickael Arditi
131
Mickael Arditi  

Hi,

I have a problem to count the number of different integer in an array.

For exemple: in MyArray {5,7,5,3,3,4,7,7,3,4,4,3}  There is 4 different integer (3, 4, 5 and 7)

I would like to return  int DifArrayNbr=4;

I've tried to did it with some "for() " or "while()" but it's so hard to make a correctly loop

Can someone help me please?

Mike

William Roeder
20208
William Roeder  
//{ Typedefs
#define  INDEX    uint           // Zero based.
#define  COUNT    uint           //  One based.
   #define INV_INDEX               UINT_MAX
   #define INV_COUNT               UINT_MAX
//} Typedefs
template <typename T>
COUNT    count_unique(T& array[], INDEX iEnd=INV_INDEX, INDEX iBeg=0){
   if(iEnd == INV_INDEX)   iEnd  = ArraySize(array);
   if(iEnd == iBeg)  return 0;            // Empty array.
   ArraySort(array, iEnd - iBeg, iBeg);
   COUNT    n  = 1;                       // Last is unique;
   while(--iEnd > iBeg) if(array[iEnd] != array[iEnd-1] )   ++n;
   return n;
}
/////////////////////////////////////////////////////
int      MyArray[] ={5,7,5,3,3,4,7,7,3,4,4,3};
COUNT    DifArrayNbr=count_unique(MyArray); // 4
aslkdjf
22
aslkdjf  
whroeder1:
What is "COUNT" and "INDEX" types?
William Roeder
20208
William Roeder  
Put on your glasses and look at the code again.
Petr Nosek
3023
Petr Nosek  
aslkdjf:
What is "COUNT" and "INDEX" types?

The both are uint. This is whroeder's style but the code is worth it. Maybe it can be improved for double and float by using DBL_EPSILON.

William Roeder
20208
William Roeder  
Petr Nosek: Maybe it can be improved for double and float by using DBL_EPSILON.
//{ Typedefs
#define  PRICE double            // A PRICE
#define     PRICE_MAX   (PRICE)EMPTY_VALUE
#define     PRICE_MIN   (PRICE)0
#define     CHANGE      PRICE    // Difference of two prices.
#define  INDEX    uint           // Zero based.
#define  COUNT    uint           //  One based.
#define  MONEY    double
#define  LOTS     double
#define  SYMBOL   string
//} Typedefs
Don't need DBL_EPSILON as Tick Size or Point is sufficient.
Icham Aidibe
11675
Icham Aidibe  
Mickael Arditi:

Hi,

I have a problem to count the number of different integer in an array.

For exemple: in MyArray {5,7,5,3,3,4,7,7,3,4,4,3}  There is 4 different integer (3, 4, 5 and 7)

I would like to return  int DifArrayNbr=4;

I've tried to did it with some "for() " or "while()" but it's so hard to make a correctly loop

Can someone help me please?

Mike

I would have do it so, it's not as nerdy as the above snippet, but it works well : 

#include <Arrays\ArrayInt.mqh> // Include lib
//
int MyArray[]={5,7,5,3,3,4,7,7,3,4,4,3};
//
int CountItem(int &Array[])
  {
   CArrayInt *TempArray=new CArrayInt(); CArrayInt *ItemsFound=new CArrayInt(); int value = 0;
   TempArray.AssignArray(MyArray); TempArray.Sort();
   for(int x=0;x<TempArray.Total();x++) { if(ItemsFound.Search(TempArray.At(x))<0) { ItemsFound.Add(TempArray.At(x)); ItemsFound.Sort(); } else { continue; } }
   printf("*** Items found in array : %g",ItemsFound.Total()); value = ItemsFound.Total();
   delete(TempArray); delete(ItemsFound);
   return(value);
  }
//
DifArrayNbr = CountItem(MyArray); // Function call
//+------------------------------------------------------------------+
Petr Nosek
3023
Petr Nosek  
whroeder1:
Don't need DBL_EPSILON as Tick Size or Point is sufficient.

I've a little bit edited your function and it gives better results in my opinion. The last element in the double array is 3 like the previous one. For price is Tick Size or Point sufficient but for indicator values...

UPDATE: see the next post

template <typename T>
uint CountUnique(T& array[],const char precision=-1,uint iEnd=UINT_MAX,const uint iBeg=0)
  {
   if(iEnd==UINT_MAX) iEnd=ArraySize(array);
   if(iEnd==iBeg) return(0); // Empty array.
   ArraySort(array,iEnd-iBeg,iBeg);
   uint count=1; // Last is unique;
   string tn=typename(T);
   if((tn=="double"||tn=="float"))
     {
      if(precision>-1)
        {
         while(--iEnd>iBeg)
            if(DoubleToString(array[iEnd],precision)!=DoubleToString(array[iEnd-1],precision)) count++;
        }
      else
         while(--iEnd>iBeg)
            if(fabs(array[iEnd]-array[iEnd-1])>DBL_EPSILON*10) count++; // Too small difference => equal
     }
   else
      while(--iEnd>iBeg) if(array[iEnd]!=array[iEnd-1]) count++;
   return(count);
  }


   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   
   double dblArr[6]={1.0000001,1.0,1.4,1.399999,3.0,90000.0*123456789123456789.0/(30000.0*123456789123456789.0)};
   int intArr[12]={5,7,5,3,3,4,7,7,3,4,4,3};
   uint DifDblArrayNbr,DifIntArrayNbr;
   
   DifDblArrayNbr=CountUnique(dblArr);    // 5 (in your case 6)
   DifDblArrayNbr=CountUnique(dblArr,6);  // 4 
   DifDblArrayNbr=CountUnique(dblArr,5);  // 3
   DifDblArrayNbr=CountUnique(dblArr,0);  // 2
   
   DifIntArrayNbr=CountUnique(intArr);    // 4
Petr Nosek
3023
Petr Nosek  

Update: less code, same results


template <typename T>
uint CountUnique(T& array[],const char precision=-1,uint iEnd=UINT_MAX,const uint iBeg=0)
  {
   if(iEnd==UINT_MAX) iEnd=ArraySize(array);
   if(iEnd==iBeg) return(0); // Empty array.
   ArraySort(array,iEnd-iBeg,iBeg);
   uint count=1; // Last is unique;
   string tn=typename(T);
   if((tn=="double"||tn=="float"))
     {
      double difference=(precision>-1 && precision<16)?(pow(10.0,-1.0*precision)-pow(10.0,-1.0*(precision+1))):DBL_EPSILON*10;
      while(--iEnd>iBeg)
         if(fabs(array[iEnd]-array[iEnd-1])>difference) count++; // Too small difference => equal
     }
   else
      while(--iEnd>iBeg) if(array[iEnd]!=array[iEnd-1]) count++;
   return(count);
  }
Mickael Arditi
131
Mickael Arditi  
Thank you very much for all your help! :) Have a very nice day ;)
To add comments, please log in or register