Syntax in reduce method - javascript

This is a solution to a toy problem in Javascript. The job was to find a Palindrome(word that you can read the same back and forth, like "radar", "rotor") in a string with words separated by spaces or return an empty string if no word fits the requirement. i understand everything but i donĀ“t know how they use the reduce method to find the word, especially the syntax " ? word : prevWord"
Could somebody explain??
function reverseString(str) {
return str.split('').reverse().join('');
}
function isPalindrome(str) {
return str === reverseString(str);
}
function getWords(str) {
return str.split(' ');
}
function findPalindrome(str) {
var words = getWords(str);
return words.reduce(function(prevWord, word) {
return isPalindrome(word) ? word : prevWord;
}, '');
}
As you can see if i use the last function
findPalindrome("this is a very good rotor");
It will return
"rotor"

Related

Replace matches with regex

I am trying to replace matches of text between dollar signs.
So the text $match$ inside Some text and $some text that matches$. should be replaced.
I have tried
text.replace(/\$.*?\$/g, function (match) {
return '_' + match + '_';
}
This works. The problem is that I want to do evaluate the match inside this function, but sometimes the evaluation didn't work, and in these cases I just want to return the original match. So it is something like
text.replace(/\$.*?\$/g, function (match) {
try {
return evaluate(match);
} catch (e) {
return match;
}
}
But with my current regex, the match contains the dollar signs from the original text. I want it to omit the dollar signs, but if the evaluation fails, then I want the original dollar signs back.
What I could do is
text.replace(/\$.*?\$/g, function (match) {
try {
return evaluate(match.replace(/\$/g, ''));
} catch (e) {
return match;
}
}
but isn't it possible in a more elegant way?
Something like this might do:
const evaluate = function(str) {
if (str && str.startsWith("t")) {return str.toUpperCase();}
throw "Gotta hava a 'T'";
};
"ab$test$cd $something$ that is $tricky$.".replace(/\$([^$]*)\$/g;, function(str, match) {
try {
return evaluate(match);
} catch(e) {
return str;
}
}); //=> "abTESTcd $something$ that is TRICKY."
But I agree with the comment that you might be better returning a different signal (undefined? null?) from evaluate rather than throwing for this case. And then the function body could simply be something like:
return evaluate(match) || str;
The point is the capturing group in the regex: /\$([^$]*)\$/g;, which becomes a parameter to the replacement function.

Why doesn't it recognize join() as a function?

I'm trying to capitalize every first letter of the given string, however every time I run the code I get the following error:
TypeError: val[i].charAt(...).toUpperCase(...).join is not a function
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
strArry.map(function (val) {
for (var i = 0; i < val.length; i++) {
return val[i].charAt(0).toUpperCase().join(' ') + strArry[i].splice(1);
};
});
}
titleCase("I'm a little tea pot");
String.protoype.toUpperCase() returns a string, and Array.prototype.join() is on the Array prototype, not the string.
You probably want something like this...
return val[i].charAt(0).toUpperCase() + val[i].slice(1);
...or possibly even better (at least shorter)...
function titleCase(str) {
return str.replace(/\b[a-z]/g, function(match) { return match.toUpperCase(); });
}
Here I am using a regex to match the first lowercase letter after a word boundary, and then using a custom replacer to return it uppercased.
If you supported more than latin, then use a Unicode range to select the characters.
toUpperCase returns a String and join is not a method on that prototype.
If you run through your code and put a typeof check in before mucking with the string, you can see:
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
strArry.map(function (val) {
for (var i = 0; i < val.length; i++) {
var temp = val[i].charAt(0).toUpperCase();
console.log(typeof temp);
return temp;
};
});
}
titleCase("I'm a little tea pot");
You need to join the Array after you've mapped it to produce the final combined value.
I propose this short piece of code which works well :
var titleCase = (str) => str.split(" ").map(el => el[0].toUpperCase().concat(el.substr(1))).join(" ");
console.log(titleCase("I'm a little tea pot"));
Figured it out with a bit a research and found that using val worked with me trying to use mpa()
function titleCase(str) {
var strArry = str.toLowerCase().split(' ');
var convert = strArry.map(function(val) {
return val.replace(val.charAt(0), val.charAt(0).toUpperCase());
});
return convert.join(' ');
}
titleCase("I'm a little tea pot");
Im am not Familiar with Javascript, which is why I fo not know if it makes a difference between char and string.
I am quite sure you meant do an entirely different thing, namely return a string joined from capitalized letters. What you are (trying) to do here however is returning the result of your expression (val[i].andsoonandsoforth) after the first cycle of your for loop.
The reason why the expression doesn't work will be that join(string) is usually called on arrays of strings or characters. You are calling it on a single character however!
The solution would be to first split uf the string into characters, capitalize them, store them into an array, call join on that array and return the thing afterwards.
Or just use the likely existent builtin capitalize functions on strings.

Javascript: palindrome function?

I have working code for a simple word flipper:
var strFlip = function(str) {
return str.split(" ").map(function(word) {
return word.split("").reverse().join("");
}).join(" ");
};
console.log(strFlip("This is designed to swap the letter order of each word in the string"));
// "sihT si dengised ot paws eht rettel redro fo hcae drow ni eht gnirts"
I want to add an if/else to allow this code to now identify if each word in a string is a palindrome (spelled the same forward and backward ex: hannah).
So I tried continuing the .map() logic with:
var strFlip = function(str) {
return str.split(" ").map(function(word) {
return word.split("").reverse().join("");
}).join(" ").toLowerCase().map(function(test) {
if (test.split(" ") === word){
return true;
}else{
return false;
}
}
);
};
console.log(strFlip("Hannah loves her racecar"));
BUT.... unsurprisingly, it returns an error essentially stating that the long linked collection of functions before the if section is not itself a function:
TypeError: str.split(...).map(...).join(...).toLowerCase(...).map is not a function
I was also getting lost trying to match all of the curly braces, but I think I got them all.
So, is it possible to add the if/else within?
.join(" ").toLowerCase() returns a string, not an array. The error is stating that 'some string'.map is not a function because it's undefined.
If what you want is an array that indicates whether a word at an index is a palindrome then...
var sentence = 'Eve drives a racecar',
words = sentence.split(" ").map(function(word) {
var isPalindrome = word.length > 1 && (word.toLowerCase() === word.toLowerCase().split("").reverse().join(""));
return { text: word, isPalindrome: isPalindrome };
});
alert(JSON.stringify(words));

Regex for alternating indexes from a word boundary

I've just finished this programming challenge on CodeWars:
Write a function toWeirdCase that accepts a string, and returns the same string with all even indexed characters in each word upper cased, and all odd indexed characters in each word lower cased. The indexing just explained is zero based, so the zero-ith index is even, therefore that character should be upper cased.
I tried to figure this out with regex before giving up and simply using a for loop with indexes. Just to confirm, the index of capitalising letters resets to 0 whenever there is a space. So ThIs Is A CoRrEcT AnSwEr but ThIs iS nOt, because every first letter of each word must be capitalised.
With that in mind, is there an approach to look for alternate (odd or even) indexes using regex? In this case, find a word boundary using \b, and then every even index from there, until the end of the word?
You can borrow map to convert apply a function to each character, i%2 to detect if i is odd, and toLowerCase or toUpperCase to change the case:
function toWeirdCase(str) {
return [].map.call(str, function(char, i) {
return char[i%2 ? 'toLowerCase' : 'toUpperCase']();
}).join('');
}
There are multiple ways to reset the index at each space. For example,
function toWeirdCase(str) {
var i = 0;
return [].map.call(str, function(char) {
if(char === ' ') i = -1;
return char[i++ % 2 ? 'toLowerCase' : 'toUpperCase']();
}).join('');
}
The function parameter to replace receives the match offset after the matched string and matched groups.
function toWeirdCase(s) {
return s.replace(/[a-zA-Z]/g, function (ltr, offset) {
return offset & 1 ? ltr.toLowerCase() : ltr.toUpperCase();
});
}
You need to split the input into words, then weird case each word:
function toWeirdCase(str) {
return str.split(' ').map(weirdCaseWord).join(' ');
}
weirdCaseWord can be written as in the other answer:
function weirdCaseWord(str) {
return str.split('').map(function(char, i) {
return char[i%2 ? 'toLowerCase' : 'toUpperCase']();
}).join('');
}
If you prefer, you could use a single map with a flag which is toggled on each character, and reset on a space:
function toWeirdCase(str) {
var even = false;
return str.split('').map(function(char) {
even = char === ' ' ? false : !even;
return char[even ? 'toUpperCase' : 'toLowerCase']();
}).join('');
}

Why is this regex not causing an error in Javascript?

I'm a bit confused about different regex formats.
The following methods are causing an error.
function validateDate(str) {
var expr = /^((((0?[1-9]|[12]\d|3[01])[\/](0?[13578]|1[02])[\/]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|[12]\d|30)[\/](0?[13456789]|1[012])[\/]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|1\d|2[0-8])[\/]0?2[\/]((1[6-9]|[2-9]\d)?\d{2}))|(29[\/]0?2[\/]((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00)))|(((0[1-9]|[12]\d|3[01])(0[13578]|1[02])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|[12]\d|30)(0[13456789]|1[012])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|1\d|2[0-8])02((1[6-9]|[2-9]\d)?\d{2}))|(2902((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00))))$/;
return validate(expr, str);
}
function validateTime(str) {
var expr = /^([0-1]?[0-9]|[2]?[0-3])\:([0-5][0-9])$/;
return validate(expr, str);
}
function validate(pattern, str) {
return str.match(pattern);
}
I've taken the following regex's from the web. I think the problem is regarding certain escape characters
What's wrong here?
Thanks : )
In the validateDate function you are assigning the regular expression object to the exp variable, but in the next line you are using the expr variable, which is undefined.
Edit:
What do you expect the functions to return? Right now they are returning an array of matches. If you want them to just return true or false, you might want to use the test method instead:
function validate(pattern, str) {
return pattern.test(str);
}

Categories

Resources