2
\$\begingroup\$

Due to an excercise, I've made a function that converts given string to spinal case just-like-this-one (all lower case). I did it with two regular expressions. Can it be done with one, or generally better?

function spinalCase(str) {
 //if string is not delimited 
 if(str.search(/[_\s]/) === -1){
 // insert dash before every uppercase letter
 return str.replace(/(?=[A-Z])/g , '-').toLowerCase();
 } else { 
 //change delimiters to dashes 
 return str.replace(/[_\s](?=[a-zA-Z])/g, '-').toLowerCase();
 }
}

edit: variable naming was forced by excercise (wouldn't complete otherwise). Example converted input:

"This Is Spinal Tap"

"thisIsSpinalTap"

"The_Andy_Griffith_Show"

"Teletubbies say Eh-oh"

asked Nov 5, 2015 at 15:47
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

This does it in two steps:

  1. Add spaces before each uppercase, which allows the uppercases to be handled by...
  2. The delimiter case. This is the same regex you already wrote, although I am collapsing multiple delimters down to a single one.

Having two transformation passes, similar to using a unix pipeline, is easier to reason about that breaking it up into two cases with an "if else".

Note the cryptic (?!^) matches "not at the beginning of a line" only

function spinalCase(str) {
 return str.replace(/(?!^)([A-Z])/g, ' 1ドル')
 .replace(/[_\s]+(?=[a-zA-Z])/g, '-').toLowerCase();
}

All of your test cases pass:

this-is-spinal-tap
this-is-spinal-tap
the-andy-griffith-show
teletubbies-say-eh-oh
answered Nov 5, 2015 at 16:49
\$\endgroup\$
2
\$\begingroup\$

Well, to start, you have 3 regexes and duplicate code. str, while it is implied as a string, should be named to something that it is, like stringToConvert.

Now you're trying to jam in a lot of different inputs into one function. I highly suggest you split them into different functions instead. This keeps them predictable and easy to maintain. This will avoid cases like "Oh! I want to preserve _" and stuff but your function clobbers it, regardless.

In that case, CamelCase piece can be simplified to the following:

function camelCaseToSpinalCase(stringToReplace) {
 return stringToReplace.replace(/[A-Z]/g, function(match, offset) {
 return (offset ? '-' : '') + match;
 }).toLowerCase();
}
document.write(camelCaseToSpinalCase('TestFooBarBazClass'));

replace accepts a string or pattern to replace and a function that generates the result. In this case, we don't have parenthesized blocks so we only get match and offset and no additional args in between. In all cases, we lowercase the text. If offset is 0, we're at the beginning of the text, meaning we don't add the dash before the text.

The snake-case piece into:

function snakeCaseToSpinalCase(stringToReplace) {
 return stringToReplace.replace(/_/g, '-').toLowerCase();
}
document.write(snakeCaseToSpinalCase('Test_Foo_Bar_Baz_Class'));

answered Nov 5, 2015 at 16:20
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Except it won't work for some variations. I should've added requirements before, sorry. Ive added example inputs that function should process correctly. \$\endgroup\$ Commented Nov 5, 2015 at 16:29

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.