DEV Community

Cover image for CodeToday: "Convert string to camel case" algorithm, CodeWars
Kurt Bauer
Kurt Bauer

Posted on

CodeToday: "Convert string to camel case" algorithm, CodeWars

The Gist

I started the morning working on an algorithm and realized it wasn't going to be a quick practice for me. I wanted to go over my thinking process, and the top solution after I submitted as well. We can always learn to be better, so why not try to think through someone's solution that seems cleaner?

The Problem

Complete the method/function so that it converts dash/underscore delimited words into camel casing. The first word within the output should be capitalized only if the original word was capitalized (known as Upper Camel Case, also often referred to as Pascal case).

  • should handle empty values
  • should remove underscores and convert first letter of word to upper case
  • should remove hyphens and convert first letter of word to upper case

My Solution

function toCamelCase(str){
  //console.log(str, 'testing')
  if(str === ''){
    return ''
  } else {

   let containmentArea = []
   let splitString = str.replace(/[^A-Z0-9]/ig, "_").split("_")
   //[ 'the', 'stealth', 'warrior' ]
   let firstElement = containmentArea.push( splitString.splice(0,1) )

   for(let word in splitString){

     let splitWords = splitString[word].split('')
     let capitalLetter = splitWords[0].toUpperCase()

     splitWords.splice(0,1, capitalLetter)
     let joinedWord = splitWords.join('')

     containmentArea.push(joinedWord)
     let newSentence = containmentArea.join('')

   }
     return containmentArea.join('')
  }
}

The Process

1) I'll have to check if there's an empty string, so I create an if/else statement.
2) First I split my string, splitString, with a regular expression

  • replace() = searches a string for a specified value, or regular expression, and returns a new string where the specified values are replaced.
  • In this case I used a regular expression, /[^A-Z0-9]/ig, in the search value.
  • The carrot, (^), is the negation operator which matches anything NOT in the character class. Some great regex resources are Regular-Expressions.info, RegexPal and this post on StackOverflow. Below I pasted an example using the RegexPal tool. Only characters that are not numbers or letters are being highlighted. Now we can see why it would find dashes in the strings I'm working on.

REGEX

Example of /[^A-Z0-9]/ig regex being used

I replaced any odd characters, so that I could know for certain that all my words are separated by the same character. I know that all my words are separated by the underscore _, so now it makes it easier for my to use the split() method to separate each word by commas, and place them in an array, [ 'the', 'stealth', 'warrior' ].

3) My next big hurdle will be capitalizing every first letter of every word...except the first word. To deal with this I used the splice() method to remove the first word from the original array, then push it into my containmentArea array. I created an array to temp hold my strings, as I plan to later use the join() method to smush them back into strings right before returning them. But there's still more work to be done.

4) On to the for loop which I wrote with the ES6 syntax. Remember that splitString is an array with my string split into comma separated elements. Let's start iterating through every element, using the variable word. I will use the split method on every word, splitString[word], to further break down my string into something that would look like
[ 's', 't', 'e', 'a', 'l', 't', 'h' ]
, for example & I'll store them in an array called splitWords.

5) I can than grab the first element in my splitWords array with splitWords[0], and transform it with the the toUppercase() method. This is how I capitalize every first letter of every word, except the first word that we splice() -d off at the start of this algorithm.

6) Since our process of transforming the first character in the string hasn't modified the original array, we'll have to do that with another splice() method, only this time we'll have to supply our method with a third value, which will be what we want to replace our un-capitalized letter with. In this case, that's represented by the capitalLetter variable in splitWords.splice(0,1, capitalLetter). And we then use our join() method to squish our letters back together into one word, ['Stealth'].

7) We still need to glue our camlCased sentence back together though. I write containmentArea.push(joinedWord) to push our words with the first capitalized into our containment array that still holds the first word we spliced off. And then use another joind, let newSentence = containmentArea.join('') to create my camelCased sentence.

8) We should be done at this point, but can't simply return the containmanetArea variable that's holding our string. This is because the initial split() we ran resulted in an array of strings, that was pushed into another array. So right before returning we use another join() to condense our two arrays into one.

This was my solution, and then after turning it in I am faced with this beautiful answer that's been voted as top:

function toCamelCase(str){

      var regExp =/[-_]\w/ig;

      return str.replace(regExp,function(match){
            return match.charAt(1).toUpperCase();
       });
}

1) The variable regExp is set to equal a regular expression to find all word characters (Alphanumeric or underscore), which is the \w portion of the regex. But with just that, you can't also highlight dashes. Which is why that symbol is proceeded by [-_], making an explicit statement that we want to match dashes and underscores. And as always, i is to ignore case, and g is for a global search. It's finding matches that when console logged to the screen would look like -S match and _s match; whis a (dash || underscore) + a (word character or number).

2) The next step is calls for a replace method, which will take the item to replace in the first parameter, and in this case a call back function in the second parameter.

The replace() method returns a new string with some or all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function to be called for each match. If pattern is a string, only the first occurrence will be replaced.

3) the charAt() method takes an index:

An integer between 0 and 1-less-than the length of the string. If the index cannot be converted to the integer or no index is provided, the default is 0...

Just like an array, we're grabbing the second character at index 1, and transforming that to uppercase to replace the dash or underscore the preceded it.

Conclusion

In just 3 steps someone was able to create a solution that was far easier to implement. Though this proves I need to brush up on my regular expressions, I'm glad I could break it down and understand every line.

stay pawsitive

Resources

Oldest comments (0)