Spinal Tap Case - better way to do this?

Spinal Tap Case - better way to do this?


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;


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


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.


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:

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('Teletubbies say Eh-oh'))
console.log(spinalCase('AllThe-small Things'))

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

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


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!


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)

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


@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?


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;


Well, it can be broken to multiple lines:

function spinalCase(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1 $2')


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


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 . 
    return str;

spinalCase('This Is Spinal Tap');