How to get rid of duplicated characters in a string

 
here is my code:
//+------------------------------------------------------------------+
//|                                                       GetRid.mq5 |
//|                                                 Babak Jafarzadeh |
//|                                           https://goodlibrary.ir |
//+------------------------------------------------------------------+
#property copyright "Babak Jafarzadeh"
#property link      "https://goodlibrary.ir"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
input string Main="aaBbc";
string NoRepMain=StringSubstr(Main,0,1);
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   int NoRepCount=StringLen(NoRepMain);
   
   for(int i=0;i<NoRepCount;i++)
     {
      string refrence=StringSubstr(NoRepMain,i,1);
      string compare;
      bool   Notduplicated=true;
      for(int j=0;j<StringLen(Main);j++)
        {
         compare=StringSubstr(Main,j,1);
         int mode=StringCompare(refrence,compare,false);
         if(mode==0)
           {
            Notduplicated=false;
           }
        }
      if(Notduplicated)
        {
         NoRepMain=NoRepMain+compare;
        }
     }
   Comment(NoRepMain);
  }
//+------------------------------------------------------------------+

No matter what I do, I end up with NoRepMain="a" part.

Don't know which part I am doing wrong. can anyone show me where I am doing wrong? thanks

 

I thought it might be because of the length of the NoRepMain so I tried this method too:


//+------------------------------------------------------------------+
//|                                                       GetRid.mq5 |
//|                                                 Babak Jafarzadeh |
//|                                           https://goodlibrary.ir |
//+------------------------------------------------------------------+
#property copyright "Babak Jafarzadeh"
#property link      "https://goodlibrary.ir"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
input string Main="aaBbc";
string NoRepMain=StringSubstr(Main,0,1);
int OnInit()
  {
//---
   
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
bool NoRepChanged=false;
void OnTick()
  {
//---
   if(NoRepChanged)
     {
      Norep();
     }
   Comment(NoRepMain);
  }
//+------------------------------------------------------------------+
void Norep()
  {
     uint NoRepCount=StringLen(NoRepMain);
   
   for(int i=0;i<(int)NoRepCount;i++)
     {
      string refrence=StringSubstr(NoRepMain,i,1);
      string compare;
      bool   Notduplicated=true;
      for(int j=0;j<StringLen(Main);j++)
        {
         compare=StringSubstr(Main,j,1);
         int mode=StringCompare(refrence,compare,false);
         if(mode==0)
           {
            Notduplicated=false;
           }
        }
      if(Notduplicated)
        {
         NoRepMain=NoRepMain+compare;
         NoRepChanged=true;
        }
     }
  }

still no change. end up with NoRepMain="a" again. HELP

 
As arrays are easier to handle I would convert a string into an array of uchar (StringToCharArray)  compare each element if they match (and or if the 'distance' is 'a' - 'A' or 'A' - 'a' [whatever is > 0]) copy them into a result array and finally I would create a sting from the result array again with CharArrayToString().
Documentation on MQL5: Conversion Functions / StringToCharArray
Documentation on MQL5: Conversion Functions / StringToCharArray
  • www.mql5.com
[in]  Number of array elements to copy. Defines length of a resulting string. Default value is -1, which means copying up to the array end, or till terminal 0. Terminal 0 will also be copied to the recipient array, in...
 
babigaf:
here is my code:

No matter what I do, I end up with NoRepMain="a" part.

Don't know which part I am doing wrong. can anyone show me where I am doing wrong? thanks

You are using StringCompare() incorrectly, check the documentation.

By the way to compare 2 strings of 1 character, you don't need this function.

 
well alain. you are always in help. for a better solution, what do I need to compare two characters? can you help me out?
 

Try this one . 
Dont forget you need to update the string as you remove replicas , get the new length again and check up to the previous to the previous to the last character.

So what is happening in there :

  1. The function gets the first character from the string
  2. It then creates a "remaining" string- called remnants- which is the rest of the string following this character
  3. Then it "strips" all similar characters from the remnant 
  4. Attaches the character under check to the preceder , and to the now clean remnant
  5. Increases the preceder by the character being checked 

(Preceder was a fast and loose term derived from preceeding)

(Also i have not tested this with Right To Left Languages , although i think it might work as in a multilingual project we noticed the editor changed RTL to LTR but display was normal)

string UnRepeat(string main,bool case_irrelevant)
{
//Initial
int ml=StringLen(main),seeker=0;
string preceder="";
while(seeker<(ml-1))
{
string character_being_checked=StringSubstr(main,seeker,1);
string character_to_upper=character_being_checked,character_to_lower=character_being_checked;
  //transformations 
  if(case_irrelevant) 
  {
  bool transf=StringToUpper(character_to_upper);
       transf=StringToLower(character_to_lower);
  }
  //transformations
string remnant=StringSubstr(main,seeker+1,ml-1);
  int replaced=-1;
  if(!case_irrelevant) replaced=StringReplace(remnant,character_being_checked,"");
  if(case_irrelevant) 
  {
  replaced=StringReplace(remnant,character_to_lower,"");
  replaced=StringReplace(remnant,character_to_upper,"");
  }
main=preceder+character_being_checked+remnant;
preceder+=character_being_checked;
ml=StringLen(main);
seeker++;
}
return(main);
}
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
  • www.mql5.com
//| Expert initialization function                                   | //| Expert deinitialization function                                 | //| Expert tick function                                             | //| test1                                                            |...
 
Carl Schreiber:
As arrays are easier to handle I would convert a string into an array of uchar ( StringToCharArray)  compare each element if they match (and or if the 'distance' is 'a' - 'A' or 'A' - 'a' [whatever is > 0]) copy them into a result array and finally I would create a sting from the result array again with CharArrayToString().

Thanks Carl. I would try this method. you guys are awesome

 

In your 1st attempt :

input string Main="aaBbc";
string NoRepMain=StringSubstr(Main,0,1);

NoRepMain="a"

NoRepCount=1

Looping only one time

---------------------------------------------------

Also can you see this part

if(Notduplicated)
        {
         NoRepMain=NoRepMain+compare;
        }

is never executed

So why always NoRepMain="a"

 

In the 2nd attempt can you see 

bool NoRepChanged=false;
void OnTick()
  {
//---
   if(NoRepChanged)
     {
      Norep();
     }
   Comment(NoRepMain);
  }

NoRep() is never executed because NoRepChanged is setted as false;

 
Lorentzos Roussos:

Try this one . 
Dont forget you need to update the string as you remove replicas , get the new length again and check up to the previous to the previous to the last character.

So what is happening in there :

  1. The function gets the first character from the string
  2. It then creates a "remaining" string- called remnants- which is the rest of the string following this character
  3. Then it "strips" all similar characters from the remnant 
  4. Attaches the character under check to the preceder , and to the now clean remnant
  5. Increases the preceder by the character being checked 

(Preceder was a fast and loose term derived from preceeding)

(Also i have not tested this with Right To Left Languages , although i think it might work as in a multilingual project we noticed the editor changed RTL to LTR but display was normal)

dude!! reading your code worth an entire class to me!! that was incredible and worked well. as you guessed, I tried it in RTL too and it works as awesome as it does in LTR. 

thanks man. I appreciate your time.

 
paul selvan:

In the 2nd attempt can you see 

NoRep() is never executed because NoRepChanged is setted as false;

yeah I feel like an idiot now :D
thanks. I read roussos code and got what I was doing entirely wrong. but love you all for the time you dedicate to this forum. thanks man

Reason: