Spinal Tap Case - better way to do this?

Spinal Tap Case - better way to do this?
0

#1

Is there a better way to solve the Spinal Tap Case by possibly combining each step into fewer lines? I’m sure changing the value of the str variable 3 times probably isn’t best practice.

function spinalCase(str) {
  str = str.replace(/([a-z])([A-Z])/g, '$1 $2'); // add space between lowercase to uppercase
  str = str.replace(/\W|_/g,'-');// change non letters to -
  str = str.toLowerCase(str.replace(/\W|_/g,'-'));// make it all lowercase
  return str;
}

#2

How about chaining the function calls? Then do something like

return str.replace(...).replace(...).replace(...);

iirc there’s a one-liner posted somewhere in this forum that uses just one replace call


#3

You don’t need the str.replace(/\W|_/g,'-') here.
As far as chaining it all into a single line - six of one/half dozen of the other. I personally prefer not to.


#4

Why do you use the same regex twice on line 3 and 4? It’s also worth checking the documentation of toLowerCase(). Anyway, a shorter solution would be:

Spoiler
function spinalCase(str) {
  str = str.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/\W|_/g,'-')
  return str.toLowerCase()
}

console.log(spinalCase('This Is Spinal Tap'))
console.log(spinalCase('thisIsSpinalTap'))
console.log(spinalCase('The_Andy_Griffith_Show'))
console.log(spinalCase('Teletubbies say Eh-oh'))
console.log(spinalCase('AllThe-small Things'))

You can even make it a one-liner by chaining them:

Spoiler
function spinalCase(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/\W|_/g,'-').toLowerCase()
}

#5

My original solution didn’t have the repeated regex on line 4 after the toLowerCase, I think I was trying to figure out how to string them together on my own and forgot to delete it before copying into the forum question.

I like the one liner solutions with stringing them all together. That’s what I was looking for but wasn’t sure how exactly you could do it with multiple replace calls. Thanks for the help everyone!


#6

Another way, better or not, would be to use split with a somewhat complex regex:

function spinalCase(str) {
  return str.split(/[-\s_]|\B(?=[A-Z])/).join('-').toLowerCase();
}

Discussion, Questions, and Resources for Part 3 of the April 2018 Cohort (Intermediate Algorithm Scripting and JavaScript Algorithms and Data Structures Projects)
#7

+1 for efficiency
-1 for readability
(The story of regex ;))


#8

@ArielLeslie, you said you prefer doing it on multiple lines, would you do it like I originally did by changing the value of the str variable each time? Or is there another way to do it on multiple lines?


#9

My solution looks very like yours

function spinalCase(str) {
  // convert (lowercase)(uppercase) to (lowercase)-(uppercase)
  str = str.replace(/([a-z])([A-Z])/g, "\$1-\$2" );
  // convert spaces and underscores to dashes
  str = str.replace(/[\s_]/g, "-");
  // lowercase
  str = str.toLowerCase();
  return str;
}

#10

Well, it can be broken to multiple lines:

function spinalCase(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1 $2')
    .replace(/\W|_/g,'-')
    .toLowerCase()
}

#11

very smart Velenir! i like the idea to split then join! cheers


#12

I reviewed positive and negative lookahead to pass this challenge and here is my workaround:


function spinalCase(str) {
  // "It's such a fine line between stupid, and clever."
  // --David St. Hubbins
  // first, I split the string to make it an array of substrings \W = [A-Za-z-0-9],(?=[A-Z])=positive lookahaed . 
    str=str=str.split(/\W|_|(?=[A-Z])/g).join("-").toLowerCase();
   
    return str;
}

spinalCase('This Is Spinal Tap');