"Better solution" at Intermediate Algorithms: Spinal Tap Case

Hi together
I passed the “Spinal Tap Case” task. But I am sure, that there are better solutions.
How can I be more efficient or readable. Or is my solution not that bad as I think?

Code:

 function spinalCase(str) {
 let res = str.replace(/\W|_/g,'-').split('');
 
 for(let i in res){
   if(/[A-Z]/.test(res[i]) && res[i-1] !== '-' && res[i-1] !== undefined){
     res.splice((i),0,'-');
   }
 }

 res = res.join('').toLowerCase();
 
 return res;
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0.

Challenge: Spinal Tap Case

Link to the challenge:

Hi @n8trufe!

I have included spoiler tags around your code for those who haven’t work on the challenge.

You can also use backticks (```) or the preformatted tool when writing code in the forum instead of (>) symbols.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

Hi @jwilkins.oboe
The tag makes makes the surrounded Text blured and the Backticks the Text formatted?
I didn’t know that.
Thank you for your hint.

1 Like

Generally using splice in loops should be avoided because it changes the original array. Although in your case you’re using splice to replace a character (which makes your code a bit confusing to read). Also your for loop itself is quite confusing.

You could tweak your regex to eliminate the for loop:

function spinalCase(str) {
  return str.replace(/([A-Z])|(_|-)/g, " $1")
    .split(" ")
    .filter(Boolean)
    .join("-")
    .toLowerCase()
}

Ok, you are MUCH better than me. Your solution is a bit confusing for me. Especially what you are doing inside the replace method. But I think I will get this.
But I have completely no idea, what you are doing with the filter method…

replace(/([A-Z])|(_|-)/g, " $1")

The braces () in regex is called capture group and it saves the result in a variable named $N where N is capture group’s order (if no match $N is an empty string).
So in this regex first capture group is [A-Z] (any capital letter) and is saved in $1.
The second capture group is _|- (underscore OR dash) and is saved in $2.
Next we replace matched result with a space plus the result in $1 (which in case of underscore or dash will result in just a space).

.filter(Boolean)

It’s a shortcut for .filter(value => Boolean(value)) (Boolean constructor takes a value and turns it into a boolean). I’m using it to filter out empty values that will be created by splitting on space if there is more than one space in a row.

In 2 days we have holidays. I will take this days to repeat the RegEx section (this is quite confusing and complex) and to understand what you wrote.
But thanks a lot for your support.