# freeCodeCamp Challenge Guide: Spinal Tap Case

**URL:** <https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078>\
**Category:** freeCodeCamp Contributors\
**Tags:** guide\
**Created:** [June 30, 2016, 11:21pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078 "2016-06-30T23:21:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![camperbot](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/camperbot/32/18364_2.png) [@camperbot](https://forum.freecodecamp.org/u/camperbot)\
**Post date:** [June 30, 2016, 11:21pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/1 "2016-06-30T23:21:28Z")

</div>

# [Spinal Tap Case](https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/spinal-tap-case)

* * *

## Problem Explanation

Convert the given string to a lowercase sentence with words joined by dashes.

#### Relevant Links

- [String global object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
- [JS Regex Resources](https://forum.freecodecamp.org/t/a-quick-and-simple-guide-to-javascript-regular-expressions/190263)
- [JS String Prototype Replace](http://forum.freecodecamp.com/t/javascript-string-prototype-replace/15942)
- [JS String Prototype ToLowerCase](http://forum.freecodecamp.com/t/javascript-string-prototype-tolowercase/15948)

* * *

## Hints

### Hint 1

Create a regular expression for all white spaces and underscores.

### Hint 2

You will also have to make everything lowercase.

### Hint 3

The tricky part is getting the regular expression part to work, once you do that then just turn the uppercase to lowercase and replace spaces with dashes using `replace()`.

* * *

## Solutions

> **Solution 1 (Click to Show/Hide)**
>
> ```javascript
> 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 -
> return str.replace(regex, "-").toLowerCase();
> }
> 
> // test here
> spinalCase("This Is Spinal Tap");
> 
> ```
> 
> #### Code Explanation
> 
> - **regex** contains the regular expression `/\s+|_+/g`, which will select all white spaces and underscores.
> - The first `replace()` puts a space before any encountered uppercase characters in the string **str** so that the spaces can be replaced by dashes later on.
> - While returning the string, another `replace()` replaces spaces and underscores with dashes using **regex**.

> **Solution 2 (Click to Show/Hide)**
>
> ```javascript
> function spinalCase(str) {
> // Replace low-upper case to low-space-uppercase
> str = str.replace(/([a-z])([A-Z])/g, "$1 $2");
> // Split on whitespace and underscores and join with dash
> return str
> .toLowerCase()
> .split(/(?:_| )+/)
> .join("-");
> }
> 
> // test here
> spinalCase("This Is Spinal Tap");
> 
> ```
> 
> #### Code Explanation
> 
> - Similar to the first solution, the first `replace()` puts a space before any encountered uppercase characters in the string **str** so that the spaces can be replaced by dashes later on.
> - Instead of using `replace()` here to replace whitespace and underscores with dashes, the string is `split()` on the regular expression `/(?:_| )+/` and `join()`-ed on `-`.
> 
> #### Relevant Links
> 
> - [JS String Prototype Split](http://forum.freecodecamp.com/t/javascript-string-prototype-split/15944)
> - [JS Array Prototype Join](http://forum.freecodecamp.com/t/javascript-array-prototype-join/14292)

> **Solution 3 (Click to Show/Hide)**
>
> ```javascript
> function spinalCase(str) {
> // "It's such a fine line between stupid, and clever."
> // --David St. Hubbins
> 
> return str
> .split(/\s|_|(?=[A-Z])/)
> .join("-")
> .toLowerCase();
> }
> 
> ```
> 
> #### Code Explanation
> 
> - Split the string at one of the following conditions (_converted to an array_)
> - a whitespace character [`\s`] is encountered
> - underscore character [`_`] is encountered
> - or is followed by an uppercase letter [`(?=[A-Z])`]
> 
> - Join the array using a hyphen (`-`)
> - Lowercase the whole resulting string
> 
> #### Relevant Links
> 
> - [String#split](http://devdocs.io/javascript/global_objects/string/split)
> - [RegExp](http://devdocs.io/javascript/global_objects/regexp)
> - [Arrray#join](http://devdocs.io/javascript/global_objects/array/join)
> - [String#toLowerCase](http://devdocs.io/javascript/global_objects/string/tolowercase)

---

<div class="post-metadata">

**Author:** ![jemagee](https://avatars.discourse-cdn.com/v4/letter/j/ecc23a/32.png) [@jemagee](https://forum.freecodecamp.org/u/jemagee)\
**Post date:** [August 10, 2016, 2:28am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/2 "2016-08-10T02:28:01Z")

</div>

So this is what I came up with myself (I am not great with regular expressions)

```javascript
function spinalCase(str) {
  // "It's such a fine line between stupid, and clever."
  // --David St. Hubbins
  str = str.replace(/[^a-zA-Z0-9-]|[a-z][A-Z]/g, function(x) {
    if (x.match(/[a-z][A-Z]/)) {
        return x[0] + "-" + x[1];
        } else {
        return "-";
        }
  });
  return str.replace(/[A-Z]/g, function(x){
    return x.toLowerCase();
  });
}

```

---

<div class="post-metadata">

**Author:** ![Rafase282](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rafase282/32/161583_2.png) [@Rafase282](https://forum.freecodecamp.org/u/Rafase282)\
**Post date:** [August 10, 2016, 2:34am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/3 "2016-08-10T02:34:29Z")

</div>

Closed on August 10, 2016, 2:34am UTC



---

<div class="post-metadata">

**Author:** ![Rafase282](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rafase282/32/161583_2.png) [@Rafase282](https://forum.freecodecamp.org/u/Rafase282)\
**Post date:** [August 20, 2016, 3:38am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/4 "2016-08-20T03:38:57Z")

</div>

Opened on August 20, 2016, 3:38am UTC



---

<div class="post-metadata">

**Author:** ![akashkriplani](https://avatars.discourse-cdn.com/v4/letter/a/e480ec/32.png) [@akashkriplani](https://forum.freecodecamp.org/u/akashkriplani)\
**Post date:** [January 9, 2017, 10:15am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/5 "2017-01-09T10:15:07Z")

</div>

@ArielLeslie @jemagee I am also not good with regular expressions, so I came up with this.

```
function spinalCase(str) {

  var result="";
  for (var i = 0; i<str.length; i++){
    
    var codeCheck = str.charCodeAt(i);
    
    if(codeCheck>=65 && codeCheck<=90){
      result+=String.fromCharCode(codeCheck+32); // converting to lower case
    }
    else if(codeCheck>=97 && codeCheck<=122){
      
      if(str.charCodeAt(i+1)>=65 && str.charCodeAt(i+1)<=90){ // if the next character is Uppercase, then add the "-"
        result+=String.fromCharCode(codeCheck);
        result+="-";
      }
      else
        result+=String.fromCharCode(codeCheck);
      } 
    else
      result+="-";
  }
  return result;
}

spinalCase('thisIsSpinalTap aBCDefK');

```

It seems to be working fine.  
If you detect any flaws in this code, kindly reply. I need to get better at regular expressions. For now, just trying to avoid the use of it.

---

<div class="post-metadata">

**Author:** ![thegreaterpanda](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@thegreaterpanda](https://forum.freecodecamp.org/u/thegreaterpanda)\
**Post date:** [January 15, 2017, 3:15pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/6 "2017-01-15T15:15:59Z")

</div>

It can be done in a single line with:  
`
return str.replace(/([a-z])([A-Z])|[_|\s]+/g, ‘$1-$2’).toLowerCase();
</>`

---

<div class="post-metadata">

**Author:** ![PinkPanther901](https://avatars.discourse-cdn.com/v4/letter/p/f08c70/32.png) [@PinkPanther901](https://forum.freecodecamp.org/u/PinkPanther901)\
**Post date:** [January 31, 2017, 9:28pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/7 "2017-01-31T21:28:17Z")

</div>

@thegreaterpanda

Could you help me understand your solution a little bit more? I like the conciseness of it, but I don’t understand the last part.

So far, this is my understanding of that code:

- Return the result of the replace method called on the string argument (thereby creating a new “str”),
- For every lower case a to z letter (RegExp), every capital A-Z letter (RegExp) -OR- underscore or blank space characters of at least one or more, global search…
- …and then the syntax for the $1 and $2 I don’t understand.

The MDN documentation says that $n takes any positive integer below 100 and assigns it to the nth “parenthesized submatch string”, assuming that the first argument fed to .replace is a RegExp object.

So, with the above syntax, I am guessing it would read: for every capital or lower case a-z OR a blank space/underscore, replace it with… that same letter or blank space? I’m really not sure. 😕

---

<div class="post-metadata">

**Author:** ![EgoDominusVos](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/egodominusvos/32/34387_2.png) [@EgoDominusVos](https://forum.freecodecamp.org/u/EgoDominusVos)\
**Post date:** [February 1, 2017, 12:07am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/8 "2017-02-01T00:07:20Z")

</div>

> [@camperbot](#):
>
> Advanced Code Solution:
> 
> function spinalCase(str) {  
> // “It’s such a fine line between stupid, and clever.”  
> // --David St. Hubbins
> 
> return str.split(/\s|\_|(?=[A-Z])/).join(‘-’).toLowerCase()  
> }

This is BUGGY -

with this string

```js
spinalCase('this_Is-SpinalCase iI')

```

it returns:

```js
this-is--spinal-case-i-i

```

which should NOT pass the 4th requirement; the return has an extra ’ - ’ in it …

---

<div class="post-metadata">

**Author:** ![thegreaterpanda](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@thegreaterpanda](https://forum.freecodecamp.org/u/thegreaterpanda)\
**Post date:** [February 2, 2017, 9:12pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/9 "2017-02-02T21:12:22Z")

</div>

Sure thing! You’re right about the first part. So the regex stores the match found in each bracket as a ‘$’ variable. It looks for a small letter next to a capital letter. Once it has found that it assigns the first letter to the ‘$1’ variable and the second letter to the ‘$2’ variable. It then replaces that match with the string on the right which contains a dash in the middle between the two characters and calls toLowerCase on the result.

---

<div class="post-metadata">

**Author:** ![danielbaars](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/danielbaars/32/161499_2.png) [@danielbaars](https://forum.freecodecamp.org/u/danielbaars)\
**Post date:** [March 17, 2017, 8:50am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/10 "2017-03-17T08:50:45Z")

</div>

I found the same thing testing it with this string: ‘AllThe-Small ThingsFor’. The combination of the hyphen and uppercase letter trips up the advanced solution but not the others. However, with your string none of the solutions work. I’m assuming you want the result to be ‘this-is-spinal-case-ii’, right? I guess this is an edge case as you would have to tell the algorithm that ‘II’ is not a word that you can split up but a roman number.

To make the solution work for my example string I added a replace to it:

```
function spinalCase(str) { 

    return str.split(/\s|_|(?=[A-Z])/).join('-').replace(/--/g, '-').toLowerCase();
	
}

```

It is not very elegant so any suggestions for improvement would be appreciated.

---

<div class="post-metadata">

**Author:** ![a-gromadzki](https://avatars.discourse-cdn.com/v4/letter/a/dbc845/32.png) [@a-gromadzki](https://forum.freecodecamp.org/u/a-gromadzki)\
**Post date:** [March 18, 2017, 12:11am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/11 "2017-03-18T00:11:49Z")

</div>

adding non capturing group like:  
`return str.split(/\s|_|(?=[A-Z])|(?:-)/).join('-').toLowerCase()`  
will get rid of - all together, since when joining we add them anyway, those fixing the issue.

As for “iI” being separated, well the idea is to catch entire words beginning with capital letter. Identifying what is basically a typing error is slightly beyond scope of this exercise I recon. Just imagine writing regex to extract the word from random mix of low and upper caps like FrEEcoDeCaMp 🙂

---

<div class="post-metadata">

**Author:** ![yodist](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/yodist/32/163076_2.png) [@yodist](https://forum.freecodecamp.org/u/yodist)\
**Post date:** [March 24, 2017, 11:52pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/12 "2017-03-24T23:52:40Z")

</div>

I’m not good enough with regex,but this is my approach.

```
function spinalCase(str) {
  // "It's such a fine line between stupid, and clever."
  // --David St. Hubbins
  var firstLet = (str.split(''))[0];
  str = str.slice(1,str.length);
  str = str.replace(/\s/g,'-');
  str = str.replace(/([A-Z])/g,'-$1');
  str = str.replace(/_/g,'-');
  str = str.replace(/-+/g,'-');
  return (firstLet + str).toLowerCase();
}

spinalCase('thisIsSpinalTap');
```

---

<div class="post-metadata">

**Author:** ![t0cc](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/t0cc/32/42441_2.png) [@t0cc](https://forum.freecodecamp.org/u/t0cc)\
**Post date:** [May 17, 2017, 8:57pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/13 "2017-05-17T20:57:05Z")

</div>

That wasn’t easy. Then I found a solution which makes me happy 😀

```
function spinalCase(str) {
  return str.replace(/(\w)[_]?([A-Z])| /g, "$1-$2").toLowerCase()
}
```

---

<div class="post-metadata">

**Author:** ![irakligeek](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/irakligeek/32/50010_2.png) [@irakligeek](https://forum.freecodecamp.org/u/irakligeek)\
**Post date:** [June 7, 2017, 12:51am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/14 "2017-06-07T00:51:04Z")

</div>

My code:

```
function spinalCase(str) {
  
  //fist deal with the Camel case strings
  str = str.split(/(?=[A-Z])/).join(" ");
  //create patterns that will be replaced
  var patterns = [/_+/g, /\s+/g,/-+/g];
  
  for(var i=0; i<patterns.length; i++){
    if(patterns[i].test(str)){
      str = str.replace(patterns[i], '-');
    }
  }
  
  return str.toLowerCase();
}

//test
spinalCase('AllThe-small Things');
```

---

<div class="post-metadata">

**Author:** ![coderdix](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/coderdix/32/54407_2.png) [@coderdix](https://forum.freecodecamp.org/u/coderdix)\
**Post date:** [June 17, 2017, 9:32pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/15 "2017-06-17T21:32:45Z")

</div>

My solution:

```
function spinalCase(str) {
  const regEx = /([a-z])([A-Z])/g;
  const regEx1 = /\s+|_+/g;
  const subst = '-';
  
  const result = str.replace(regEx, '$1-$2')
                    .replace(regEx1, '-')
                    .toLowerCase();
  
  return result
}

spinalCase('This Is Spinal Tap');
```

---

<div class="post-metadata">

**Author:** ![Dude1983](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/dude1983/32/159846_2.png) [@Dude1983](https://forum.freecodecamp.org/u/Dude1983)\
**Post date:** [June 22, 2017, 3:10pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/16 "2017-06-22T15:10:30Z")

</div>

Here’s the solution that worked for me:

```
function spinalCase(str) {
  
  regExp = /[\W_,.]/g;
  
  return str.replace(regExp, '-')
                .replace(/([a-z\d])([A-Z])/g, '$1-$2')
                .toLowerCase();   
}
```

---

<div class="post-metadata">

**Author:** ![rblanco\_fcc](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rblanco_fcc/32/63634_2.png) [@rblanco\_fcc](https://forum.freecodecamp.org/u/rblanco_fcc)\
**Post date:** [July 3, 2017, 9:23pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/17 "2017-07-03T21:23:41Z")

</div>

I got some trouble with this challenge, but finally I managed to solve it. My major problem was the “upper case letter condition” to insert a “-”. I know there are short and easy ways to solve this using regExp but it’s a bit complicated for me since I don’t have so much practice in that (by now), so I wanted to find my way through this challenge.

 ![](https://global.discourse-cdn.com/freecodecamp/original/3X/d/1/d140e20893684aa259bcf7629bf16ef8def38b14.JPG)

---

<div class="post-metadata">

**Author:** ![killyridols](https://avatars.discourse-cdn.com/v4/letter/k/ccd318/32.png) [@killyridols](https://forum.freecodecamp.org/u/killyridols)\
**Post date:** [July 13, 2017, 12:40pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/18 "2017-07-13T12:40:41Z")

</div>

```auto
function spinalCase(str) {
  // replace spaces [/s] and underscore [_]
  return str.replace(/[\s_]/g, "-")
            // replace lowercase letter [a-z] followed by uppercase letter [A-Z]
            .replace(/[a-z](?=[A-Z])/g, function(match) {
              match = match + "-";
              return match;
            })
            .toLowerCase();
}

```

---

<div class="post-metadata">

**Author:** ![rodrigodiego](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/rodrigodiego/32/59117_2.png) [@rodrigodiego](https://forum.freecodecamp.org/u/rodrigodiego)\
**Post date:** [July 21, 2017, 11:57am UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/19 "2017-07-21T11:57:03Z")

</div>

It’s not elegant code but…

```
function spinalCase(str) {

  str = str.replace(/ /g, "-");
  str = str.replace(/_/g, "-");
  str = str.replace(/[A-Z]/g,replacer);

  function replacer(match, offset, string) {
    return (offset ? '-' : '') + match.toLowerCase();
  }

  str = str.replace(/--/g, "-");
  
  return str;
}
spinalCase("This Is Spinal Tap");
```

---

<div class="post-metadata">

**Author:** ![Master-Osaro](https://sea3.discourse-cdn.com/freecodecamp/user_avatar/forum.freecodecamp.org/master-osaro/32/161670_2.png) [@Master-Osaro](https://forum.freecodecamp.org/u/Master-Osaro)\
**Post date:** [July 22, 2017, 7:35pm UTC](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078/20 "2017-07-22T19:35:01Z")

</div>

```
function spinalCase(str) {
  // "It's such a fine line between stupid, and clever."
  // --David St. Hubbins
  var arr = str.split("");
  var regEx = /[A-Z]/g;
  for(var i =0; i<arr.length;i++){
    if(regEx.test(arr[i])){
      if (i!=0){
      arr.splice(i, 0, " ");
      }
    }   
  }      
  var filtered = arr.join("").toLowerCase().replace(/_/g," ").replace(/\s+/g," ").replace(/[^A-Za-z0-9]/g,"-");      
  return filtered;
  //finito
}

```

I really need to get better with regular expressions. Some algorithms here have just three to four lines of code!! I’ll get there soon though. I’ll get there. 🙂

[Next page](https://forum.freecodecamp.org/t/freecodecamp-challenge-guide-spinal-tap-case/16078.md?page=2)
