简体   繁体   中英

Caesar Cipher in Javascript using shiftChar() function and Array.map() method

I am attempting to learn Javascript by reading through a lot of online tutorials, and am practicing by working through the challenges on coderbyte. I am having trouble with the CaesarCipher challenge. The function needs to take a string and an offset parameter, and then return the string with each alpha character shifted by whatever offset was provided (leaving any non-alpha characters intact). I've got my shiftChar() function working, which will take the char and the offset and will apply the shift only for alpha characters and will return the new character. Now that that is complete, I thought I would be able to just take the original string, split it into an array, and then map that array of chars to a new array using my shiftChar() function. However, I can't get it to work and I can't seem to figure out why.

Is there something I am missing about the map method? My understanding is that the map method will automatically pass each element in the array it is called on as the first argument. Then I am just passing my offset value as an additional argument. Can someone please shed some light as to why this is not working and suggest a more workable approach?

/*
Using the JavaScript language, have the function CaesarCipher(str,num) take the str parameter and perform a Caesar Cipher shift on it using the     num parameter as the shifting number. A Caesar Cipher works by shifting each letter in the string N places down in the alphabet (in this case N will be num). Punctuation, spaces, and capitalization should remain intact. For example if the string is "Caesar Cipher" and num is 2 the output should be "Ecguct Ekrjgt". 
*/

var str = 'Caesar Cipher';

function CaesarCipher(str, offset){  
  var charArray = str.split('');
  var result = charArray.map( shiftChar( char, offset )).join('');  

  function shiftChar(char, offset){
    var isAlpha = /[A-z]/;

    if(isAlpha.test(char)){
      char = String.fromCharCode(char.charCodeAt(0) + offset);
      if(char > 'Z' && char < 'a' || char > 'z')
        char = String.fromCharCode(char.charCodeAt(0) - 26);
    }
    return char;
  }
  return result;
}

console.log(CaesarCipher( str, 2));

If you need to parameterize your shiftChar function when you map over the array, you can curry it so that it takes one parameter at a time:

function shiftChar(offset) {
    return function(char) {
        var isAlpha = /[a-z]/i;

        if(isAlpha.test(char)){
          char = String.fromCharCode(char.charCodeAt(0) + offset);
          if(char > 'Z' && char < 'a' || char > 'z')
            char = String.fromCharCode(char.charCodeAt(0) - 26);
        }
        return char;
    }
}

so you'd have to call it as shiftChar(22)('a') to shift the letter "A" by 22.

This lets you do "Hello".split("").map(shiftChar(22)); .

There are a few things in your code stopping you from getting the intended results.

Array.map() returns an array, it doesn't modify the original array. In your example you are storing the new array into result , but your function is returning the original charArray , and not result , which is what you want.

The 2nd issue is the callback function you are providing to map . The first argument of map should be a function, but shiftChar( char, offset) is not a function, it is the result of calling shiftChar . (I hope this part makes sense). Typically when working with map , you create an anonymous function which will receive the arguments specified in the documentation below. In your case, you would want to do the following:

var result = charArray.map( function(char) { return shiftChar(char, offset); } ).join('');

Array.map reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

full jsfiddle example: http://jsfiddle.net/p2fkLs2t/

This should work:

var str = 'Caesar Cipher';

function CaesarCipher(str, offset){  
  var charArray = str.split('');

  function shiftChar(char){
    var isAlpha = /[a-z]/i;

    if(isAlpha.test(char)){
      char = String.fromCharCode(char.charCodeAt(0) + offset);
      if(char > 'Z' && char < 'a' || char > 'z')
        char = String.fromCharCode(char.charCodeAt(0) - 26);
    }
    return char;
  }

  var result = charArray.map( shiftChar ).join('');  

  return result;
}

console.log(CaesarCipher( "test", 2));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM