Objective
Create a function to convert a given string into title case.
Description
Consider the string 'This is great.'
. If we are to convert this string into title casing in a naive way, we'd get the string 'This Is Great.'
.
Title casing can be performed in a multitude of ways, some taking into account certain elements of English grammar such as prepositions and certain conjunctions. There is no universal title casing standard and so different implementations have different rules.
For us, we define title casing in a very naive way. That is, a string in title case is one where the first character of every word is in upper case.
As mentioned before, the string 'This Is Great.'
is in title case. The words 'This', 'Is' and 'Great.' all have their first characters in upper case.
Note that here our definition of a word is simply a sequence of characters with a space on its left or its right. Hence, the string 'Superb stunt'
constitutes two words whereas the string 'Awe-inspiring'
constitutes just one word.
In this exercise, you have to create a function toTitleCase()
that converts a given string into title case, as discussed above, and then returns it.
Your solution MUST NOT use any array methods.
Shown below are a handful of examples of the function's usage:
toTitleCase('This is great.')
toTitleCase('An awe-inspiring story!')
toTitleCase('10 tips to become successful')
toTitleCase('hello world!')
toTitleCase('HELLO WORLD!')
toTitleCase(' ')
toTitleCase('')
Note the string 'HELLO WORLD!'
here. It was already in upper case and hence there was no effect of converting it into title case.
Hints
Hint 1
Use the split()
string method, with the delimiter ' '
, to break the given string into an array of words.
Hint 2
Iterate over all words in the array obtained by splitting the given string, and then uppercase each word's first character.
Hint 3
In the end, join all the words in the array into a single string with a space character (' '
) between them.
New file
Inside the directory you created for this course on JavaScript, create a new folder called Exercise-19-Title-Casing and put the .html solution files for this exercise within it.
Solution
First, let's set up the basic structure of the function:
function toTitleCase(str) {
// Code to go here.
}
Now, let's convert the given string str
into a sequence of words (whose definition is given in the exercise's description above).
This can very easily be accomplished using the split()
string method, passing in the string ' '
as the delimiter, as follows:
function toTitleCase(str) {
var words = str.split(' ');
}
With the array of words in hand, what we ought to do next is to uppercase the first character of every word. This can be done by iterating over all the words and replacing each one with its corresponding first-character-uppercased version.
In the code below, we do exactly this:
function toTitleCase(str) {
var words = str.split(' ');
for (var i = 0, len = words.length; i < len; i++) {
words[i] = words[i][0].toUpperCase() + words[i].slice(1);
}
}
- The first character of
words[i]
, which is the current word in the loop, is accessed aswords[i][0]
and then uppercased using the methodtoUpperCase()
. - Then this uppercased character is concatenated with the remainder of the string, which is extracted with the help of the
slice()
method. - Finally, the result of the concatenation is written back to
words[i]
.
Now, as the second-last step, we just need to join all the words in the array words
using a space character in between them. That is, if words
is ['A', 'B', 'C']
, then we need to produce the string 'A B C'
, with a space between each of the words.
This also can be accomplished very simply using a for
loop and an accumulator string variable meant to hold the concatenation of all words along with the space character, as demonstrated below:
function toTitleCase(str) {
var words = str.split(' ');
for (var i = 0, len = words.length; i < len; i++) {
words[i] = words[i][0].toUpperCase() + words[i].slice(1);
}
var titleCasedStr = words[0];
for (i = 1, i < len; i++) {
titleCasedStr += ' ' + words[i];
}
}
Perfect, so far.
The final thing left is to just return the string titleCasedStr
. This is done below:
function toTitleCase(str) {
var words = str.split(' ');
for (var i = 0, len = words.length; i < len; i++) {
words[i] = words[i][0].toUpperCase() + words[i].slice(1);
}
var titleCasedStr = words[0];
for (i = 1; i < len; i++) {
titleCasedStr += ' ' + words[i];
}
return titleCasedStr;
}
Seemingly, we might think that we've completed our function's definition, but that's not the case.
When the given string is ''
, the return value must ideally be ''
. But, as of now, our toTitleCase()
function doesn't return ''
when it's passed in with ''
. In fact, it returns nothing, but instead throws an error.
The snippet below illustrates this:
toTitleCase('')
The error message hints us that the problem lies in the line where the toUpperCase()
method is invoked, and that is in line 5.
So what could be the problem there?
Well, when we split the empty string ''
using the split()
string method, we get back an array consisting of one single item, which is an empty string as well. That is, we get the array ['']
.
In the subsequent for
loop (lines 4 - 6), when we access words[i][0]
, the expression words[i]
resolves to ''
, and then words[i][0]
resolves to undefined
. Thereafter, accessing the toUpperCase()
method on undefined
throws an error.
Now the solution of this problem is to address the empty string string right at the start of the function. But still that won't solve all such problems. For instance, if we provide ' '
as the string, split()
produces the array ['', '']
, whereby there are two empty strings.
Therefore, a more generic, and a working, solution is to check if words[i]
is ''
, and if it ain't, only then proceed with invoking the toUpperCase()
method. And for this, we'll use the &&
operator.
Shown below is the complete definition of toTitleCase()
:
function toTitleCase(str) {
var words = str.split(' ');
for (var i = 0, len = words.length; i < len; i++) {
words[i] = words[i] && words[i][0].toUpperCase() + words[i].slice(1);
}
var titleCasedStr = words[0];
for (i = 1; i < len; i++) {
titleCasedStr += ' ' + words[i];
}
return titleCasedStr;
}
Now, let's test this function:
toTitleCase('This is great.')
toTitleCase('An awe-inspiring story!')
toTitleCase('10 tips to become successful')
toTitleCase('hello world!')
toTitleCase('HELLO WORLD!')
toTitleCase(' ')
toTitleCase('')
Voila! It works just as desired.