Reputation: 7739
I am stuck on this coding challenge Spinal Tap Case from freeCodeCamp. Essentially I don't know how to get the last check to execute.
This is the last check:
spinalCase("AllThe-small Things") should return "all-the-small-things"
And this is my code:
function spinalCase(str) {
var outputString,
newstr,
pattern1 = new RegExp(/[_\s]/, 'g'),
pattern2 = new RegExp(/(?=[A-Z])/, 'g'),
stringTest1 = pattern1.test(str),
stringTest2 = pattern2.test(str);
if(stringTest1) {
outputString = str.replace(pattern1, '-');
newstr = outputString.toLowerCase();
} else if(stringTest2) {
str.split(/(?=[A-Z])/).join(' ');
outputString = str.replace(pattern2, '-');
newstr = outputString.toLowerCase();
} else if (stringTest1 && stringTest2){
outputString = str.replace(pattern1, '-');
outputString = str.replace(pattern2, '-');
newstr = outputString.toLowerCase();
}
return newstr;
}
I do realize the last else if
condition should go first however I didn't get the syntax right.
Thanks in advance!
Upvotes: 7
Views: 6598
Reputation: 1216
I have no illusions that anybody is going to care now ;), but I would have searched for positions in-between words, as indicated by capital letters, and placed hyphens there instead. For example:
const spinalCase = (str) => {
let regex = /(?:\B|[ _])(?=[A-Z])/g;
return str.replace(regex, '-').toLowerCase();
}
console.log(spinalCase('AllThe-small Things'));
Upvotes: 0
Reputation: 83
I've come up with the following. For the FCCamp purpose it works
function spinalCase(str) {
return str
.split(/(?=[A-Z])/)
.join()
.split(/[_\W+]/)
.join(' ')
.split(/\s+/)
.join('-')
.toLowerCase()
}
spinalCase("AllThe-small Things");
Upvotes: 1
Reputation: 11
A beginner friendly solution:
function spinalCase(str) {
//change camelCase to title case(i.e. change 'markIsHere' to 'Mark Is Here')
let newStr = str.replace(/([a-z])([A-Z])/g, ('$1 $2'));
//replace space with '-'
newStr = newStr.replace(/ /g, '-');
//replace underscores with '-'
newStr = newStr.replace(/_/g,'-');
//change the result to lowercase
return newStr.toLowerCase()
}
Upvotes: 1
Reputation: 1
function insert(arr){
arr = arr.split("");
for(let i in arr){
if (/[A-Z]/.test(arr[i])&& i>0){
arr[i] = "-" + arr[i];
}
}
arr = arr.join("");
return arr;
}
function spinalCase(str) {
str = str.split(/\s+|_/);
str = str.map(item=>insert(item));
str = str.join("-");
str = str.toLowerCase();
return str;
}
Upvotes: 0
Reputation: 53
I was stuck on this too, but found a simpler solution:
function spinalCase(str) {
const regex =new RegExp(/(([A-Z]|[a-z])[a-z]+)/,'g');
str=str.match(regex);
return str.join('-').toLowerCase();
}
console.log(spinalCase('AllThe-small things'));
Upvotes: 1
Reputation: 79
function spinalCase(str) {
//Split the string at one of the following conditions
//a whitespace character [\s] is encountered
//underscore character [_] is encountered
//or by an uppercase letter [(?=[A-Z])]
//Join the array using a hyphen (-)
//Lowercase the whole resulting string
return str.split(/\s|_|(?=[A-Z])/).join('-').toLowerCase();
}
Upvotes: 3
Reputation: 515
function spinalCase(str) {
var newStr = '';
var arr = str.split('');
for (var i = 0; i < arr.length; i += 1) {
if (i > 0) {
if (arr[i] >= 'A' && arr[i] <= 'Z') {
if (arr[i - 1] >= 'a' && arr[i - 1] <= 'z') {
newStr += '-';
newStr += arr[i].toLowerCase();
continue;
}
}
else if (arr[i] === ' ' || arr[i] === '_') {
newStr += '-';
continue;
}
}
newStr += arr[i].toLowerCase();
}
return newStr;
}
spinalCase("AllThe-small Things");
Upvotes: 1
Reputation: 1131
Here's my solution, simple with regex and works for all cases
function spinalCase(str) {
return str.replace(/([A-Z])/g,' $1') /*Find all cap and add space at the start*/
.replace(/[^A-Za-z0-9]/g,' ') /*Find all non alpha numeric and replace it with space*/
.replace(/\s{1,}/g,"-") /*Convert all spaces to -*/
.replace(/^\-|[\-]$/g,'') /*Slice - at the start and end*/
.toLowerCase(); /*LowerCase it*/
}
Upvotes: 4
Reputation: 758
function spinalCase(str) {
// any string followed by upperCase letter
var re = /(?=[A-Z])/g;
// any string followed by space and upperCase/lowerCase letter
var re2=/(?=\s[A-Z]|\s[a-z])/g;
// any string of 2 or more '-'
var re3 = new RegExp("-{2,}", "g");
var space = new RegExp(" ","g");
var hyphen = new RegExp("_","g");
str = str.replace(hyphen,"-");
str = str.replace(re, '-');
str = str.replace(re2,"-");
str = str.replace(re3,"-");
str = str.replace(space,"");
str = str.toLowerCase();
if(str.slice(0,1)== '-'){
str = str.replace("-","");
}
return str;
}
spinalCase('This Is Spinal Tap');
Upvotes: 1
Reputation: 1893
here's my solution, a bit less heavy on the regex:
function spinalCase(str) {
var newStr = str[0];
for (var j = 1; j < str.length; j++) {
// if not a letter make a dash
if (str[j].search(/\W/) !== -1 || str[j] === "_") {
newStr += "-";
}
// if a Capital letter is found
else if (str[j] === str[j].toUpperCase()) {
// and preceded by a letter or '_'
if (str[j-1].search(/\w/) !== -1 && str[j-1] !== "_") {
// insert '-' and carry on
newStr += "-";
newStr += str[j];
}
else {
newStr += str[j];
}
}
else {
newStr += str[j];
}
}
newStr = newStr.toLowerCase();
return newStr;
}
Upvotes: 1
Reputation: 1
function spinalCase(str) {
// Create a variable for the white space and underscores
var regex = /\s+|_+/g;
// Replace low-upper case to low-space-uppercase
str = str.replace(/([a-z])([A-Z])/g, '$1 $2');
// Replace space and underscore with dashes
return str.replace(regex, '-').toLowerCase();
}
Upvotes: 0
Reputation: 13888
Here is how I recommend doing it:
function sp(str) {
var spinal = str.replace(/(?!^)([A-Z])/g, ' $1')
.replace(/[_\s]+(?=[a-zA-Z])/g, '-').toLowerCase();
return spinal
}
as far as your code, you check for:
if test1
else if test2
, then else if test1 and test2
, the logic is not correct:
you could try to adding a !test2
or !test1
to the first if checks to get it working:
if (stringTest1 && !stringTest2)...
EDIT:
here is how you can get your code to fire in that last else if, I put a console.log in there to show you here:
function spinalCase(str) {
var outputString,
newstr,
pattern1 = new RegExp(/[_\s]/, 'g'),
pattern2 = new RegExp(/(?=[A-Z])/, 'g'),
stringTest1 = pattern1.test(str),
stringTest2 = pattern2.test(str);
if(stringTest1 && !stringTest2) {
outputString = str.replace(pattern1, '-');
newstr = outputString.toLowerCase();
} else if(!stringTest1 && stringTest1) {
str.split(/(?=[A-Z])/).join(' ');
outputString = str.replace(pattern2, '-');
newstr = outputString.toLowerCase();
} else if (stringTest1 && stringTest2){
console.log('were in the last else!!!');
outputString = str.replace(pattern1, '-');
outputString = str.replace(pattern2, '-');
newstr = outputString.toLowerCase();
}
return newstr;
}
Upvotes: 7