Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript replace every letter in the string with the letter following it in the alphabet error

Tags:

javascript

I'm trying to replace every letter in the string with the letter following it in the alphabet.

example:

a -> b  
b -> c  
c -> d  

and so on.

function LetterChanges(str) {
    for (var i = 0; i < str.length; i++) {
        if (96 < str.charCodeAt(i) && str.charCodeAt(i) < 123) {
            str = str.replace(str.charAt(i), String.fromCharCode(str.charCodeAt(i) + 1));
        }
    }
    return str;
}

so I test is with some string input, I got error on "cod", my code returned "epd" instead of "dpe", can someone please help me with fixing it?

Thanks.

like image 493
Jackie Avatar asked Jan 07 '23 08:01

Jackie


2 Answers

Let's see what the code will do with input cod:

  • Process c, next letter in alphabet is d, replace c for d, result is dod
  • Process o, next letter in alphabet is p, replace o for p, result is dpd
  • Process d, next letter in alphabet is e, replace d for e, result is epd

You see the error at step 3? replace replaces first occurence of the letter the way you use it. One solution would be to create new string by appending the next letters to it. For instance:

var newString = '';
for (var i = 0; i < str.length; i++) {
    if (96 < str.charCodeAt(i) && str.charCodeAt(i) < 123) {
        newString += String.fromCharCode(str.charCodeAt(i) + 1);
    }
 }
 return newString;

By the way, your code also has one subtle bug. If your string contains z it will be replaced for {. You probably want to go back to the beginning of the alphabet and replace it for a in that case.

like image 90
Bohuslav Burghardt Avatar answered Jan 31 '23 07:01

Bohuslav Burghardt


Since your replace is not restricted to specific positions within the string, it will replace the first matching character each time. (It does not replace all, because it does not have the g modifier set.) So first your leading c gets replaced by d, the next round replaces the o by p – and then, in the third round, when your input is already dpd, you get epd as a result, because the first d has been replaced by e.

This would be easier, if you did not use replace, but simply build a new string, that you append the matching “next” character for your current input character to each time, and then at the end you simply return that new string.

Edit:

Also, you current implementation does not handle z correctly, since it replaces it with the “next” character {, whereas that should rather be an a. And Z becomes [, should be A instead. And between Z and a, there is also a couple of non-letter characters, that you probably don’t want to replace as well.

Here is a function that implements what I suggested above, and also takes z and Z, and the non-letters into account:

function LetterChanges(str) {
    var result = "";
    for (var i = 0; i < str.length; i++) {
        // handle "z"
        if (122 == str.charCodeAt(i)) {
            result += "a";
        // handle "Z"
        } else if (90 == str.charCodeAt(i)) {
            result += "A";
        // handle all other letter characters
        } else if ((65 <= str.charCodeAt(i) && str.charCodeAt(i) <= 89) ||
                   (97 <= str.charCodeAt(i) && str.charCodeAt(i) <= 121)) {
            result += String.fromCharCode(str.charCodeAt(i) + 1);
        // append all other characters unchanged
        } else {
            result += str.charAt(i);
        }
    }
    return result;
}

console.log(LetterChanges("AaZz+cod!foo")); // output: BbAa+dpe!gpp

http://jsfiddle.net/hvyft64p/3/

if ((65 <= str.charCodeAt(i) && str.charCodeAt(i) <= 89) ||
    (97 <= str.charCodeAt(i) && str.charCodeAt(i) <= 121))

I used 65/89 and 97/121, and <= for comparison here, since it just makes a little more sense to me from a logical point of view – these are the actual “boundary” letters we want to take into account here, A/Y and a/y, so using those numbers directly makes the code a little more readable IMHO.

like image 32
CBroe Avatar answered Jan 31 '23 07:01

CBroe