Capitalizing first letter of each word in string

Hi everyone!
Sorry if this is the wrong place, but here’s something I’m curious about-

I’ve been working through some online learn to code things, and the challenge for this one was to capitalize the first letter of each word in a string.

Now looking online I found a piece of code that works:

function titleCase(str) {  
  str = str.toLowerCase().split(' ');

  for(var i = 0; i < str.length; i++){
    str[i] = str[i].split('');
    str[i][0] = str[i][0].toUpperCase(); 
    str[i] = str[i].join('');
  }
  return str.join(' ');
}
titleCase("I'm a little tea pot");

So my question is, once it’s turned into an array, I’m unlcear how i++ knows to move to the next word, not just the next letter.

For the life of me everything I can find online doesn’t touch on this and it’s driving me crazy : )

Any insight or resources would be greatly appreciated : D

I added comments, so hopefully this will explain everything…

function titleCase(str) {
     str = str.toLowerCase().split(' ');                // will split the string delimited by space into an array of words

     for(var i = 0; i < str.length; i++){               // str.length holds the number of occurrences of the array...
          str[i] = str[i].split('');                    // splits the array occurrence into an array of letters
          str[i][0] = str[i][0].toUpperCase();          // converts the first occurrence of the array to uppercase
          str[i] = str[i].join('');                     // converts the array of letters back into a word.
     }
     return str.join(' ');                              //  converts the array of words back to a sentence.
}
titleCase("I'm a little tea pot");

Personally, I’d use a little more memory and put it into different variables, but that’s just my opinion…

function titleCase(str) {
     words = str.toLowerCase().split(' ');

     for(var i = 0; i < words.length; i++) {
          var letters = words[i].split('');
          letters[0] = letters[0].toUpperCase();
          words[i] = letters.join('');
     }
     return words.join(' ');
}
titleCase("I'm a little tea pot");

Or better yet, use a regular expression, but my regEx ninja skills are VERY rusty, so I don’t want to lead you down that path…

I don’t think that regex can change a string to be titlecase.

Oh, and only one split is needed in the above code examples too.
And why are we lowercasing everything? Abbreviations such as NASA will be then turned in to Nasa.

Yes it can - here’s an example that outputs ‘Hello World’ to the console.

console.log('hello world'.replace(/\b[a-z]/g,function(f){return f.toUpperCase();}));

no splits or loops or anything like that needed - just a string match using a regular expression as the find parameter and a function as the replace parameter.

1 Like

The I’m breaks that, I’m afraid (I started with something similar, but the contraction was where I got lost)

a small modification to fix that - start of string or whitespace character followed by a letter rather than any boundary followed by a letter

console.log("help i'm sick".replace(/(^|\s)[a-z]/g,function(f){return f.toUpperCase();}));
1 Like

Nice work - I wasn’t quite sure of that.

In this case are the occurrences the words?

So I imagine it goes (roughly):
-splits string at spaces into individual words
-counts how many words
-capitalizes the first letter of each word
-joins them back into a string

In this case though, I’m still unclear as to how this knows to do this for each word instead of just treating the entire string as one long array and Only capitalizing the first letter of the entire thing, leaving the rest lower case.

I hope this makes sense. I get what it’s doing, but I don’t feel confident I could replicate this in another situation since I’m unclear as to the “why” behind the scenes : )

Hi,

Try this code i think this will help for you

var str = "hello world"; str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) { return letter.toUpperCase(); }); alert(str); //Displays "Hello World"

Though this is helpful, I’m mainly curious on how this one particular method works : )

Thank you though!

see here we are getting the strings and trying to convert to lowercase and replacing with reg exp so what are the text you are giving it will automatically change the first letter to capitalizing

if you like the code kindly like the heart icon for like the post

Your code example seems to have been copied from Stack Overflow, and doesn’t answer the specific question asked here, so it seems more than averagely inappropriate for you to be asking for likes.

1 Like

What part of the brief explanation I posted when I originally posted this solution back in post 4 of this thread didn’t you understand?

/(^|\s)[a-z]/g

matches any letter preceded by whitespace or the beginning of the string. I originally had \b boundary but as was pointed out that breaks by converting i’m to I’M

function(f){return f.toUpperCase();

takes the values returned by the regular expression and processes them. Here we are only interested in the full string returned so we don’t need a second parameter to reference the capturing group created by the ( ) around the first half of the string. The function returns that string converted to uppercase. Converting whitespace to uppercase has no effect so we don’t need to wrap the [a-z] in ( ) to reference it as the third parameter.

As we have these as the two parameters to a replace call the regular expression finds the characters in the string that need to be updated and the function defines what to replace them with. A string replace can have plain text or a regular expression as the first (find) parameter and either plain text (which may contain special values referring back to the regular expression) or a function as the second parameter providing the value to replace the value that matched the first string with.

1 Like

Here’s a useful way to use the regular expression that Felgall provided before.
I’ve unpacked his example with a few named variables and functions, to help make it easier to talk about the code and understand what it does.

function upperCase(str) {
    return str.toUpperCase();
}
function titleCase(str) {
    var firstLetterRx = /(^|\s)[a-z]/g;
    return str.replace(firstLetterRx, upperCase);
}
var result = titleCase("help i'm sick"); // "Help I'm Sick"

The firstLetterRx is a regular expression (thus the rx naming convention) that matches starting lowercase letters.

Here’s a railroad diagram that shows the structure of the regular expression:

/(^|\s)[a-z]/g

/…/g

The forward slashes delimit the regular expression itself. Normally a regular expression gives you only the first match, so the letter g afterwards says that it does a global match across the whole string, finding all matching situations in the string.

(^|\s)

The (^|\s) part is a group that looks for two different types of situations. The ^ symbol is an anchor that matches the position before the start of a string, and the \s is a character class that represents whitespace, which could be tabs, newlines, or just spaces too. The | symbol results in alternation, so that either of the anchor or the whitespace class are considered to be a valid match.

##(…)

The parenthesis also form what is called a capture group, but we’re not using that in this situation. Capture groups let you use \1 and \2 notation to replace a captured section of a string with another string. Instead of doing that, we are only using the parenthesis to gain the benefit of using alternation, so that we can match both the whitespace before a character, as well as the first letter of a string.

##[a-z]

The [a-z] part of the regular expression is a character class, that says any lowercase letter from a through to z is considered valid.

##Matched strings

When the regular expression is used on a string, such as “help i’m sick”, it will result in a certain number of matches within that string. In this case those matches are, “h”, " i", and " s".

That’s the job of the regular expression all finished.

##The replace method

From here, the replace method passes those matched strings to a replacement function that we have called upperCase. Those strings return from it converted to uppercase, and the replace method replaces the original parts of the string that it found, with the returned result from the replacement function.

As you can see, str.replace(firstLetterRx, upperCase); does all of the work to achieve title case of the string.

7 Likes

I’m still becoming accustomed to Regex and it tends to go over my head right now- your previous answer was helpful, but not in regards to the code that had been supplied : )

Your explanation here though certainly helped me understand the Regex version- and makes it seem like the much simpler option!

thank you!

Your best bet on figuring out how the code works is to run it through a debugger to see exactly what’s it’s doing.

What I normally do is have a test.html file that is linked to a test.js file and then once I have the code in my test.js file I load up the test.html file in Chrome, right click to inspect element to get to the developer tools, go to sources, bring up my test.js file, set a breakpoint, step into the function and then step over each step. It will highlight exactly what the code is doing and if you hover over variables and methods it will show you the values.

Good luck.

1 Like

How do you set a breakpoint part way through a regular expression?

[quote=“felgall, post:18, topic:209644, full:true”]How do you set a breakpoint part way through a regular expression?
[/quote]

I don’t think that you can set a breakpoint part way through a regular expression.

Let’s find someone to provide a counter-example to that one :smile:

Yes (hence why I provided the second iteration of the script, which put the variables into “human readable” scripting. A slightly bigger memory hit, but sometimes it’s needed for people learning.

It splits the original string up by each “word” because of how the first split is parameterized - it splits it by a space (the portion inside the single quotes). The second split doesn’t have a delimiter, so it splits by character.

1 Like