function spinalCase(str) {
for ( var i = 0; i < str.length; i++) {
if ( i == 0 && /[A-Z]/.test(str[i]) ) {
str.replace(str[i], str[i].toLowerCase()) }
else if ( i !== 0 && /[A-Z]/.test(str[i])) {
str.replace(str[i], " " + str[i].toLowerCase()); } }
return str.replace(/\s+/ig, "-");
}
I have passed this test actually, but I still don't understand what did I miss here. Can somebody help me?
Many thanks
For why the code "passed this test actually" I have no answer - the test code must be defective.
What has been missed is that the string.replace method returns a new string with a replacement made if a match for the first argument string was found, or an unmodified copy of the original string if no match was found. The string on which replace is called remains unchanged.
So, while the str.replace() calls may replace characters, the updated string returned by the call is not captured.
STOP!! Why not creating it with simple array methodes? I created it with javascript streams which is worth to learn. You can check all functions here. I also added a few comments to help you understanding it:
function spinalCase(str) {
return str.split(" ") //splits the string into pieces at spaces
.map(c => c.toLowerCase()) //makes each piece lowercase
.join("-"); //combines each piece with a "-"
}
console.log(spinalCase("This Is Spinal Tap"));
console.log(spinalCase("Okay nice"));
console.log(spinalCase("Super amazing streams!"));
If you have more questions just ask below in the comments.
Related
I'm able to successfully target only the letters in my string, however I am having trouble converting only the letters to their unicode values. Please help.
function LetterChanges(str) {
for(var i = 0; i < str.length; i++){
if(str.charCodeAt(i) > 64 && str.charCodeAt(i) < 127){
str.repalce(i, charCodeAt(i));
}
}
console.log(str)
}
LetterChanges("hello*3");
function LetterChanges(str) {
var newStr = ""; // the result string
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c > 64 && c < 127) {
newStr += String.fromCharCode(c + 1);
}
else {
newStr += String.fromCharCode(c);
}
}
return newStr;
}
console.log(LetterChanges("hello*3"));
If you want to replace only alphabetic characters a-z, you can do it using a regular expression like this:
function LetterChanges(str) {
return str.replace(/[a-z]/gi, function(m) {
return String.fromCharCode(
m.charCodeAt(0) + 1
);
});
}
console.log(LetterChanges("Hello*3"));
I actually think this looks a lot better as a one liner. I actually needed to do this in an interview recently and they seemed pretty impressed by the conciseness of my solution
So instead I would use this:
function letterChange(str){
return String.fromCharCode.apply(null,Array.prototype.map.call(str,i=>i.charCodeAt(0)+1));
}
Also not that the i=>u.charCodeAt(0) is a lambda function and will not work in all web browsers without use of a transpiler. You could also use this if you are still using es5:
function letterChange(str){
return String.fromCharCode.apply(null,Array.prototype.map.call(str,function(i){
return i.charCodeAt(0)+1;
}));
}
To explain this a little more lets break it down:
the first thing that may raise questions is the 'apply' function. Apply takes 2 parameters, an object (irrelevant in this case so we use null), and an array of parameters. These parameters are then passed in comma separated form to the function that we call apply on. In the case of fromCharCode, passing multiple parameters returns a String composed of all of the results. Next, we are passing it 'Array.prototype.map.call' which allows us to call the array literal function map on a String which does not come with map out of the box. We then pass this the function to apply and return the full result.
Answer #Wiktor Stribiżew suggested:
function myValidate(word) {
return (word.length === 1 || /[^A-Z]/i.test(word)) ? true : false;
}
Hello during the creation of an array I have a function that will not allow words with certain characters etc to be added to the array
function myValidate(word) {
// No one letter words
if (word.length === 1) {
return true;
}
if (word.indexOf('^') > -1 || word.indexOf('$') > -1) {
return true;
}
return false;
}
It seems like not the proper way of going about this and ive been looking into a regex that would handle it but have not been successful implementing it, tried numerous efforts like:
if (word.match('/[^A-Za-z]+/g') ) {
return true;
}
can some one shed some light on the proper way of handling this?
I suggest using a simpler solution:
function myValidate(word) {
return (word.length === 1 || /[^A-Z]/i.test(word)) ? false : true;
}
var words = ["Fat", "Gnat", "x3-2741996", "1996", "user[50]", "definitions(edit)", "synopsis)"];
document.body.innerHTML = JSON.stringify(words.filter(x => myValidate(x)));
Where:
word.length === 1 checks for the string length
/[^A-Z]/i.test(word) checks if there is a non-ASCII-letter symbol in the string
If any of the above condition is met, the word is taken out of the array. The rest remains.
EDIT: using test instead of match
You want to use test() because it returns a bool telling you if you match the regex or not. The match(), instead, always returns the matched elements. Those may be cast to true by coercion. This is not what you want.
To sum it all up you can just use this one-liner (no if needed and no quotes either, cannot get any simpler):
return word.test(/^[a-zA-Z][a-zA-Z]+$/); // two letter words
You should whitelist characters instead of blacklisting. That's one of the principles in security. In your case, don't tell what is wrong, but tell what is right:
if (word.test('/^[a-zA-Z]+$/')) { // two letter words
return false;
}
This will return false for all words that contain ONLY [a-zA-Z] characters. I guess this is what you want.
Your regex, instead, looked for illegal characters by negating the character group with the leading ^.
Two recommendations:
Just use regex in a positive way (without negation) and it'll be a lot easier to understand.
Also, validation functions normally return true for good data and false for bad data.
It is more readable this way:
if (validate(data))
{
// that's some good data we have here!
}
I am sure there is probably a dupe of this here somewhere, but if so I cannot seem to find it, nor can I glue the pieces together correctly from what I could find to get what I need. I am using JavaScript and need the following:
1) Replace the first character of a string with it's Unicode aware capitalization UNLESS the next (second) character is a - OR ` or ' (minus/dash, caret, or single-quote).
I have come close with what I could find except for getting the caret and single quote included (assuming they need to be escaped somehow) and what I believe to be a scope issue with the following because first returns undefined. I am also not positive which JS/String functions are Unicode aware:
autoCorrect = (str) => {
return str.replace(/^./, function(first) {
// if next char is not - OR ` OR ' <- not sure how to handle caret and quote
if(str.charAt(1) != '-' ) {
return first.toUpperCase(); // first is undefined here - scope??
}
});
}
Any help is appreciated!
Internally, JavaScript uses UCS-2, not UTF-8.
Handling Unicode in JavaScript isn't particularly beautiful, but possible. It becomes particularly ugly with surrogate pairs such as "🐱", but the for..of loop can handle that. Do never try to use indices on Unicode strings, as you might get only one half of a surrogate pair (which breaks Unicode).
This should handle Unicode well and do what you want:
function autoCorrect(string) {
let i = 0, firstSymbol;
const blacklist = ["-", "`", "'"];
for (const symbol of string) {
if (i === 0) {
firstSymbol = symbol;
}
else if (i === 1 && blacklist.some(char => char === symbol)) {
return string;
}
else {
const rest = string.substring(firstSymbol.length);
return firstSymbol.toUpperCase() + rest;
}
++i;
}
return string.toUpperCase();
}
Tests
console.assert(autoCorrect("δα") === "Δα");
console.assert(autoCorrect("🐱") === "🐱");
console.assert(autoCorrect("d") === "D");
console.assert(autoCorrect("t-minus-one") === "t-minus-one");
console.assert(autoCorrect("t`minus`one") === "t`minus`one");
console.assert(autoCorrect("t'minus'one") === "t'minus'one");
console.assert(autoCorrect("t^minus^one") === "T^minus^one");
console.assert(autoCorrect("t_minus_one") === "T_minus_one");
My whole goal was to write a loop that would take a string, count the letters and return two responses: one = "this word is symmetric" or two = "this word is not symmetric". However the code I wrote doesn't console anything out. Here's the code:
var arya = function(arraycount){
for (arraycount.length >= 1; arraycount.length <= 100; arraycount++) {
while (arraycount.length%2 === 0) {
console.log("This is a symmetric word and its length is " + " " arraycount.length " units.");
arraycount.length%2 != 0
console.log("Not a symmetric word");
}
}
}
arya("Michael");
There are many ways to accomplish your goal, but here are a few. The first is a somewhat naïve approach using a for loop, and the second uses recursion. The third asks whether the string equals the reverse of the string.
iterative (for loop) function
var isPalindromeIteratively = function(string) {
if (string.length <= 1) {
return true;
}
for (var i = 0; i <= Math.floor(string.length / 2); i++) {
if (string[i] !== string[string.length - 1 - i]) {
return false;
}
}
return true;
};
This function begins by asking whether your input string is a single character or empty string, in which case the string would be a trivial palindrome. Then, the for loop is set up: starting from 0 (the first character of the string) and going to the middle character, the loop asks whether a given character is identical to its partner on the other end of the string. If the parter character is not identical, the function returns false. If the for loop finishes, that means every character has an identical partner, so the function returns true.
recursive function
var isPalindromeRecursively = function(string) {
if (string.length <= 1) {
console.log('<= 1');
return true;
}
var firstChar = string[0];
var lastChar = string[string.length - 1];
var substring = string.substring(1, string.length - 1);
console.log('first character: ' + firstChar);
console.log('last character: ' + lastChar);
console.log('substring: ' + substring);
return (firstChar === lastChar) ? isPalindromeRecursively(substring) : false;
};
This function begins the same way as the first, by getting the trivial case out of the way. Then, it tests whether the first character of the string is equal to the last character. Using the ternary operator, the function, returns false if that test fails. If the test is true, the function calls itself again on a substring, and everything starts all over again. This substring is the original string without the first and last characters.
'reflecting' the string
var reflectivePalindrome = function(string) {
return string === string.split('').reverse().join('');
};
This one just reverses the string and sees if it equals the input string. It relies on the reverse() method of Array, and although it's the most expressive and compact way of doing it, it's probably not the most efficient.
usage
These will return true or false, telling you whether string is a palindrome. I assumed that is what you mean when you say "symmetric." I included some debugging statements so you can trace this recursive function as it works.
The Mozilla Developer Network offers a comprehensive guide of the JavaScript language. Also, here are links to the way for loops and while loops work in JS.
I have a function which checks if a given character is capital letter and returns true of false value:
function isUpperCase(aCharacter)
{
return (aCharacter >= 'A') && (aCharacter <= 'Z');
}
Now I have a string of characters e.g. ThksAbcdEvat.
I want to write a function which checks every character in a string and when it encounters a capital letter is will execute function decryptW but only on a block of letters until next capital letter.
Function decryptW works fine on single words. So what im looking for is execution of function 'decryptW' on 'Thks' 'Abcd' 'Evat' and return 3 words as a result. all i have at the moment is:
function decryptMessage(cipherText, indexCharacter, plainAlphabet, cipherAlphabet)
{
for (var count = 0, count < cipherText.length; count++)
{
while (isUpperCase(cipherText.charAt(count))
{
if (count - lastCapital > 1)
{
decryptWord(cipherText, indexCharacter, plainAlphabet, cipherAlphabet);
lastCapital = count;
}
}
}
}
Can you tell me if I'm even close to what I want to achieve? Any help would be much appreciated.
Probably regular expression can help you
var re = /[A-Z][a-z]*/;
var s = 'ThksAbcdEvat';
s.replace(re, function(c){
//do something with c
return c;
});
For what you describe (if I understood right) using String.replace/split will do the job of splitting up the string on its capitals:
'ThksAbcdEvat'.replace(/(.(?=[A-Z]))/g,'$1,').split(',');
//=> Thks,Abcd,Evat
Where /(.(?=[A-Z]))/g means: find any character followed by a capital A to Z, and the replacement ('$1,') means: add a ',' (comma) to the found character(s).
After that you can run a loop to apply decryptWord to every word in the array (/g means: global, i.e. do that for the whole string). So your whole decryptMessage function could look like:
function decryptMessage(cipherText /*,... other params*/ ){
var captalWords = cipherText.replace(/(.(?=[A-Z]))/g,'$1,').split(',');
for (var i=0;i<capitalWords.length;i++){
decryptWord(captalWords[i] /*,... other params*/ );
}
}
I'd say, no real need for complex while loops etc. here.