It's a Caesar cipher program, I have written this code by myself and want to convert this for loop into .map JavaScript built-in function, I have tried so many times but can't figure out.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
There are many questions on .map on this website but that doesn't work for me.
function rot13(str) {
var chArray = [];
str = str.split("");
for(var i in str){
var char = str[i].charCodeAt(0);
if(/[A-M]/g.test(str[i])){
chArray.push(char + 13);
}
else if(/[N-Z]/g.test(str[i])){
chArray.push(char - 13);
}
else chArray.push(char);
}
str = String.fromCharCode.apply(String,chArray);
return str;
}
rot13("SERR PBQR PNZC");
Below is a simple adaptation of your code to use map (used a variable rotation to avoid duplicated code):
function rot13(str) {
str = str.split("");
var encryptedChArray = str.map(char => {
var rotation = 0;
if(/[A-M]/g.test(char)){
rotation = 13;
}
else if(/[N-Z]/g.test(char)) {
rotation = -13;
}
return char.charCodeAt(0) + rotation;
});
return String.fromCharCode.apply(String, encryptedChArray);
}
console.log(rot13("SERR PBQR PNZC"));
You can split the string into an array of characters, and then map over it, performing the transformations, and then at the end, join the array of transformed characters back to a string.
function rot13(str) {
// get the char code for the character
const charCode = str.charCodeAt(0);
if(/[A-M]/g.test(str)){
return String.fromCharCode(charCode + 13);
}
else if(/[N-Z]/g.test(str)){
return String.fromCharCode(charCode - 13);
}
else {
return String.fromCharCode(charCode);
}
}
// first split the string into an array of single characters
const newString = "SERR PBQR PNZC".split("").map(rot13).join('');
console.log(newString);
If you want to do this very compactly, you can do the following:
const A = 'A'.charCodeAt(0)
const M = 'M'.charCodeAt(0)
const N = 'N'.charCodeAt(0)
const Z = 'Z'.charCodeAt(0)
function rot13(str) {
var chArray = [];
return String.fromCharCode(...(
str.split('')
.map(c => c.charCodeAt(0))
.map(c =>
(A <= c && c <= M) ? c + 13 :
(N <= c && c <= Z) ? c - 13 :
c
)
))
}
console.log(rot13("SERR PBQR PNZC"))
Another option would be to use array.map here.
The mapping method takes in a callback, and that callback takes as parameter each of the elements in the array.
Example:
var arr = [1,2,3,4,5];
arr.map(someFunc);
var someFunc = function(currentItem){
console.log(currentItem);
//This will output 1
//2
//...
}
Therefore you can define you cypher transformation inside of the someFunc that you pass to map.
Suppose you want to encode the following string
var secretMessage = "hello"
msgArray = secretMessage.split("");
msgArray.map(cypher);
var cypher = function(i){
///doStuff
}
Related
I'm starting my adventure with javascript and i got one of first tasks.
I must create function that count letter that most occur in string and write this in console.
For example:
var string = "assssssadaaaAAAasadaaab";
and in console.log should be (7,a) <---
the longest string is 7 consecutive identical characters (yes, before count i use .toLowerCase();, because the task requires it)
So far I have it and I don't know what to do next.
Someone want to help?
var string = "assssssadaaaAAAasadaaab";
var string = string.toLowerCase();
function writeInConsole(){
console.log(string);
var count = (string.match(/a/g) || []).length;
console.log(count);
}
writeInConsole();
One option could be matching all consecutive characters using (.)\1* and sort the result by character length.
Then return an array with the length of the string and the character.
Note that this will take the first longest occurrence in case of multiple characters with the same length.
function writeInConsole(s) {
var m = s.match(/(.)\1*/g);
if (m) {
var res = m.reduce(function(a, b) {
return b.length > a.length ? b : a;
})
return [res.length, res.charAt(0)];
}
return [];
}
["assssssadaaaAAAasadaaab", "a", ""].forEach(s => {
s = s.toLowerCase();
console.log(writeInConsole(s))
});
Another example when you have multiple consecutive characters with the same length
function writeInConsole(s) {
let m = s.match(/(.)\1*/g);
if (m) {
let sorted = m.sort((a, b) => b.length - a.length)
let maxLength = sorted[0].length;
let result = [];
for (let i = 0; i < sorted.length; i++) {
if (sorted[i].length === maxLength) {
result.push([maxLength, sorted[i].charAt(0)]);
continue;
}
break;
}
return result;
}
return [];
}
[
"assssssadaaaAAAasadaaab",
"aaabccc",
"abc",
"yyzzz",
"aa",
""
].forEach(s => {
s = s.toLowerCase();
console.log(writeInConsole(s))
});
I'm no sure if this works for you:
string source = "/once/upon/a/time/";
int count = 0;
foreach (char c in source)
if (c == '/') count++;
The answer given by using regular expressions is more succinct, but since you say you are just starting out with programming, I will offer a verbose one that might be easier to follow.
var string = "assssssadaaaAAAasadaaab";
var string = string.toLowerCase();
function computeLongestRun(s) {
// we set up for the computation at the first character in the string
var longestRunLetter = currentLetter = string[0]
var longestRunLength = currentRunLength = 1
// loop through the string considering one character at a time
for (i = 1; i < s.length; i++) {
if (s[i] == currentLetter) { // is this letter the same as the last one?
currentRunLength++ // if yes, reflect that
} else { // otherwise, check if the current run
// is the longest
if (currentRunLength > longestRunLength) {
longestRunLetter = currentLetter
longestRunLength = currentRunLength
}
// reset to start counting a new run
currentRunLength = 1
currentLetter = s[i]
}
}
return [longestRunLetter, longestRunLength]
}
console.log(computeLongestRun(string))
I have a string
var str = 'string'
I have a multiplier
var mult = 3
I want to return stringstringstring
The mult will change. Basically mult is kind of like a power but this is a string not a number. And I need to return multiple strings. I'm thinking of looping where mult = the number of times to loop and each would conceptually 'push' but I don't want an array or something like =+ but not a number. I'm thinking I could have the output push to an array the number of times = to mult, and then join the array - but I don't know if join is possible without a delimiter. I'm new at javascript and the below doesn't work but it's what I'm thinking. There's also no ability to input a function in the place I'm running javascript and also no libraries.
var loop = {
var str = 'string'
var arr = [];
var mult = 3;
var i = 0
for (i = 0, mult-1, i++) {
arr.push('string'[i]);
}
}
var finalString = arr.join(''); // I don't know how to get it out of an object first before joining
Not sure if what I want is ridiculous or if it's at all possible
You mean something like below,
var str = 'string'
var mult = 3
var str2 = ''
for(i = 0; i < mult; i++) {
str2 += str
}
console.log(str2)
var str = 'string'
var mult = 3;
var sol =""
while(mult--) {
sol +=str;
}
console.log(sol)
Using resusable function:
const concatStr= (str, mult)=>{
var sol =""
while(mult--) {
sol +=str;
}
console.log(sol)
}
concatStr("string",3)
Using the inbuilt Array.from method:
var str = "string"
var mult = 3
var sol = Array.from({length: mult}, ()=> str).join("")
console.log(sol)
function concatString(str, mult) {
var result = ''
for(i = 0; i < mult; i++) {
result = result.concat(str);
}
return result;
}
const value = concatString('string', 3);
console.log(value);
Also you can use array inbuilt methods,
const mult = 3, displayVal = 'str';
Array(mult).fill(displayVal).join('');
// the string object has a repeat method
console.log('string'.repeat(3));
I am trying to change the characters of a string using for loop. My aim is to change each character with the following one. For example a should be converted to b, b is to c and finally z to a, etc. I have written the following code but it doesn't work.
function LetterChanges(str) {
var char = "abcdefghijklmnoprstuvyz";
for(var i = 0; i < char.length; i++) {
var newStr = str.replace(/char[i]/gi, char[i + 1]); // the problem is here
}
return newStr;
}
// keep this function call here
console.log(LetterChanges(readline()));
You could find a letter and replace with a function.
function LetterChanges(str) {
var char = "abcdefghijklmnoprstuvyz";
return str.replace(/[a-z]/gi, c => char[char.indexOf(c) + 1] || char[0]);
}
console.log(LetterChanges('foobar'));
in a single row:
const LetterChanges = (str=‘’) => String.fromCharCode(...[...str].map(c => c.charCodeAt(0) +1));
or if you prefer:
function LetterChanges(str = ‘’) {
return String.fromCharCode(...[...str].map(c => c.charCodeAt(0) +1));
}
So I am trying to map the number of times a char appears in a string. I know that in C++ it would be.
std::string str = "AbBAaaaa";
std::unordered_map<char, int> myMap;
for(auto i = str)
{
++mymap[i];
}
How would I translate this to JavaScript?
I would reduce the string into an object indexed by character. The function passed to reduce is called for each element in the input, where the first argument (the a) is the accumulator, which is either the initial value ({} here) or what the last iteration returned. The second argument (the char) is the current character being iterated over.
const str = "AbBAaaaa";
const charCounts = Array.prototype.reduce.call(str, (a, char) => {
a[char] = (a[char] || 0) + 1;
return a;
}, {});
console.log(charCounts);
You could also use
const charCounts = [...str].reduce((a, char) => // ...
which is shorter and probably a bit easier to understand at a glance, but unnecessarily creates an intermediate array from the str.
The imperative version of this, with a for loop, would look like:
const str = "AbBAaaaa";
const charCounts = {};
for (let i = 0; i < str.length; i++) {
const char = str[i];
charCounts[char] = (charCounts[char] || 0) + 1;
}
console.log(charCounts);
Javascript already has map and you can achieve same result of your C++ app as shown in this snippet
function charOccurances(str) {
var myMap = {};
if(str.length!==0){
for (let i = 0; i < str.length; i++) {
myMap[str[i]] = (myMap[str[i]] || 0) + 1;
}
}
return myMap;
}
const str = "AbABaaaa";
console.log(charOccurances(str));
function LetterChanges(str) {
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (var i = 0; i < str.length; i++) {
var index = alphabet.indexOf(str[i])
if (/[a-zA-Z]/.test(str[i])) {
str = str.replace(str[i], alphabet.charAt(index + 1));
}
if (/[aeiou]/.test(str[i])) {
str = str.replace(str[i], alphabet.charAt(index + 26));
}
}
return str;
}
When I call LetterChanges("hello"), it returns 'Ifmmp' which is correct, but when "sent" is passed it returns 'ufOt' instead of 'tfOu'. Why is that?
str.replace() replaces the first occurrence of the match in the string with the replacement. LetterChanges("sent") does the following:
i = 0 : str.replace("s", "t"), now str = "tent"
i = 1 : str.replace("e", "f"), now str = "tfnt"
i = 2 : str.replace("n", "o"), now str = "tfot", then
str.replace("o", "O"), now str = "tfOt"
i = 3 : str.replace("t", "u"), now str = "ufOt"
return str
There are several issues. The main one is that you could inadvertently change the same letter several times.
Let's see what happens to the s in sent. You first change it to t. However, when it comes to changing the final letter, which is also t, you change the first letter again, this time from t to u.
Another, smaller, issue is the handling of the letter z.
Finally, your indexing in the second if is off by one: d becomes D and not E.
You can use String.replace to avoid that:
function LetterChanges(str) {
return str.replace(/[a-zA-Z]/g, function(c){
return String.fromCharCode(c.charCodeAt(0)+1);
}).replace(/[aeiou]/g, function(c){
return c.toUpperCase();
});
}
But there is still a bug: LetterChanges('Zebra') will return '[fcsb'. I assume that is not your intention. You will have to handle the shift.
Try this one:
function LetterChanges(str) {
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var result = '';
var temp;
for (var i = 0; i < str.length; i++) {
var index = alphabet.indexOf(str[i])
if (/[a-zA-Z]/.test(str[i])) {
//str = str.replace(str[i], alphabet.charAt(index + 1));
temp= alphabet.charAt(index + 1);
index = index+1;
}
else if(str[i] == ' '){
temp = ' ';
}
if (/[aeiou]/.test(temp)) {
temp = alphabet.charAt(index + 26);
}
result += temp;
}
return result;
}
var str = 'bcd12';
str = str.replace(/[a-z]/gi, function(char) { //call replace method
char = String.fromCharCode(char.charCodeAt(0)+1);//increment ascii code of char variable by 1 .FromCharCode() method will convert Unicode values into character
if (char=='{' || char=='[') char = 'a'; //if char values goes to "[" or"{" on incrementing by one as "[ ascii value is 91 just after Z" and "{ ascii value is 123 just after "z" so assign "a" to char variable..
if (/[aeiuo]/.test(char)) char = char.toUpperCase();//convert vowels to uppercase
return char;
});
console.log(str);
Check this code sample. There is no bug in it. Not pretty straight forward but Works like a charm. Cheers!
function LetterChanges(str) {
var temp = str;
var tempArr = temp.split("");//Split the input to convert it to an Array
tempArr.forEach(changeLetter);/*Not many use this but this is the referred way of using loops in javascript*/
str = tempArr.join("");
// code goes here
return str;
}
function changeLetter(ele,index,arr) {
var lowerLetters ="abcdefghijklmnopqrstuvwxyza";
var upperLetters ="ABCDEFGHIJKLMNOPQRSTUVWXYZA";
var lowLetterArr = lowerLetters.split("");
var upLetterArr = upperLetters.split("");
var i =0;
for(i;i<lowLetterArr.length;i++){
if(arr[index] === lowLetterArr[i]){
arr[index] = lowLetterArr[i+1];
arr[index]=arr[index].replace(/[aeiou]/g,arr[index].toUpperCase());
return false;
}
if(arr[index] === upLetterArr[i]){
arr[index] = upLetterArr[i+1];
arr[index]=arr[index].replace(/[aeiou]/g,arr[index].toUpperCase());
return false;
}
}
}
// keep this function call here
// to see how to enter arguments in JavaScript scroll down
LetterChanges(readline());