Home > front end >  Using str.replace in a for loop without losing last iteration
Using str.replace in a for loop without losing last iteration

Time:04-20

So currently I am working on a piece of code where I am given a string and need to count how many times each character in the string appears and if it appears only once replace it with a x and if it appears more than once replace it with a y. EG: "Scores" => "yxxxxy".

my current code is

public static string changeWord(string word)
    {
        var Pl = word;
        var pj = Pl;
        string alpha = "abcdefghijklmnopqrstuvwxyz";

        for (int i = 0; i < alpha.Length; i  )
        {
            var count = word.Count(x => x == alpha[i]);
            Console.WriteLine(count);

            if (count > 1)
            {
                Pl = word.Replace(alpha[i], 'y');
                
            }
            else if (count == 1)
            {
                Pl = word.Replace(alpha[i], 'x');
                
            }
        }

        return Pl;
    }
 

The count works and shows the the correct count for each letter but only changes the last one in the code so "Please" => "Pleaxe" I don't know how to get .replace to keep my new string.

CodePudding user response:

There's a problem in your algorithm: once converted letter to x you then should process letter x itself, e.g.

initial:              box
after 'b' processed:  xox
after 'o' processed:  xxx # note, that x appeared 3 time now
after 'x' processed:  yyy  

That's why instead of changing existng word, I suggest using StringBuilder and build the new string:

    public static string changeWord(string word) {
      if (string.IsNullOrEmpty(word))
        return word;

      StringBuilder sb = new StringBuilder(word);

      for (int i = 0; i < sb.Length;   i)
        if (sb[i] >= 'a' && sb[i] <= 'z')
          sb[i] = word.Count(c => c == sb[i]) > 1 ? 'y' : 'x';

      return sb.ToString();
    }

In case of long word, too many Count can be time consuming; you can try caching them:

    public static string changeWord(string word) {
      if (string.IsNullOrEmpty(word))
        return word;

      StringBuilder sb = new StringBuilder(word);

      Dictionary<char, int> counts = new Dictionary<char, int>();

      for (int i = 0; i < sb.Length;   i)
        if (sb[i] >= 'a' && sb[i] <= 'z') {
          if (!counts.TryGetValue(sb[i], out int count)) {
            count = word.Count(c => c == sb[i]);

            counts.Add(sb[i], count);
          }

          sb[i] = count > 1 ? 'y' : 'x';
        }

      return sb.ToString();
    }

CodePudding user response:

Try this:

public static string changeWord(string word)
        {
            string alpha = "abcdefghijklmnopqrstuvwxyz";

            for (int i = 0; i < alpha.Length; i  )
            {
                var count = word.Count(x => x == alpha[i]);
                Console.WriteLine(count);

                if (count > 1)
                {
                    word = word.Replace(alpha[i], 'y');

                }
                else if (count == 1)
                {
                    word = word.Replace(alpha[i], 'x');

                }
            }

            return word;
        }

CodePudding user response:

This method makes the job you want

public static string changeWord(string word)
    {
        var wordToEdit = word;
        string alpha = "abcdefghijklmnopqrstuvwxyz";

        for (int i = 0; i < alpha.Length; i  )
        {
            var count = word.Count(x => x == alpha[i]);

            if (count > 0)
            {
                wordToEdit = wordToEdit.Replace(alpha[i], count == 1 ? 'x' : 'y');
            }
        }

        return wordToEdit;
    }
  • Related