'JavaScript replace every letter in the string with the letter following it in the alphabet error
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.
Solution 1:[1]
Let's see what the code will do with input cod
:
- Process
c
, next letter in alphabet isd
, replacec
ford
, result isdod
- Process
o
, next letter in alphabet isp
, replaceo
forp
, result isdpd
- Process
d
, next letter in alphabet ise
, replaced
fore
, result isepd
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.
Solution 2:[2]
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.
Solution 3:[3]
It is not a good idea to change str
while you are looping over it.
Here is adapted function that will work.
function LetterChanges(str) {
var strOut='';
for (var i = 0; i < str.length; i++) {
if (96 < str.charCodeAt(i) && str.charCodeAt(i) < 123) {
strOut += String.fromCharCode(str.charCodeAt(i) + 1);
}
}
return strOut;
}
Solution 4:[4]
Looks like a classic Cezar's Cipher to me (for lower alplha and right shift)
function cezarCipher(str,step){
var res="";
step=step%26; //make sure the step is in range
for(var i=0,j=str.length;i<j;i++){
var nextCode=str.charCodeAt(i)+step;
if(nextCode>122){
nextCode=96+(nextCode-123+1);
}
res+=String.fromCharCode(nextCode);
}
return res;
}
Make the step=1 to get your result.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | |
Solution 4 | SebastianGreen |