Tell us what’s happening:
I think I must be misunderstanding a concept here. I have split the sentence into an array made it lower case. I then iterate through each sting in the array using a for loop. At each iteration I capitalise the first letter of the string and assign it to a variable called newLetter. I then create a regular expression to locate the first character of the sting and use the replace method to replace it with the new letter. However after all this when I then console.log(newStr) it results in the same lower case array and the fist letters have not been replace?
Any help appreciated!
Your code so far
function titleCase(str) {
var newStr = str.toLowerCase()
console.log(newStr)
newStr = newStr.split(" ")
console.log(newStr)
for (i = 0; i < newStr.length; i++){
var newLetter = newStr[i][0].toUpperCase()
console.log(newLetter)
var regex = /^./
newStr[i].replace(regex,newLetter)
console.log(newStr)
}
return str;
}
titleCase("I'm a little tea pot");
Your browser information:
User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36.
Still getting to grips with the concept of immutable in functioning code.
I have edited it and as far as I can tell in my editor it works correctly but it doesn’t pass any tests? Any guidance?
Looking at the solutions it seems I took a more literal system approach to the problem, can you suggest ways to follow the same method but streamline it?
function titleCase(str) {
var lcStr = str.toLowerCase()
console.log(lcStr)
lcStr = lcStr.split(" ")
console.log(lcStr)
var newStr = ''
for (i = 0; i < lcStr.length; i++){
var ucLetter = lcStr[i][0].toUpperCase()
console.log('This is cycle ' + i + ' ' + ucLetter)
var regex = /^./
newStr = newStr.concat(' ',lcStr[i].replace(regex,ucLetter))
console.log(newStr)
}
console.log(newStr);
return newStr;
}
titleCase("I'm a little tea pot");
It seems you are adding a space at the beginning…
to confirm write console.log("-->" + newStr + "<--") instead of the one checking newStr now. Or whatever else. If there is a space between the symbol and the beginning or the end of the string you will know you are adding extra spaces
hint: strings are immutable, but arrays are not. You can change the elements of the array.
Ah good spot. So this was because I wanted to ad a space between the concat strings. To get around this I put in an if statment that will only insert a space after the first word. Now it all seems correct but still won’t pass. Any suggestion? I suppose instead of trying to concat strings I could edit each word in the array and use .join to just provide spaces between. could be simpler.
function titleCase(str) {
var lcStr = str.toLowerCase()
console.log(typeof(lcStr))
console.log(lcStr)
lcStr = lcStr.split(" ")
console.log(typeof(lcStr))
console.log(lcStr)
var newStr = ''
for (i = 0; i < lcStr.length; i++){
var ucLetter = lcStr[i][0].toUpperCase()
console.log('This is cycle ' + i + ' ' + ucLetter)
var regex = /^./
if (i == 0) {
newStr = newStr.concat('',lcStr[i].replace(regex,ucLetter))
console.log(newStr)
} else {
newStr = newStr.concat(' ',lcStr[i].replace(regex,ucLetter))
console.log(newStr)
}
}
console.log(newStr)
return newStr;
}
titleCase("sHoRt AnD sToUt");
I have also taken a look at this simple solution
function titleCase(str) {
return str.toLowerCase().replace(/(^|\s)\S/g, L => L.toUpperCase());
}
I understand everything up until the L=> L.toUpperCase(). This is in the section that tells the replace method what to replace the regex with. Am I correct in saying that it is replacing it with the result of an anonymous function? If so, what indicates that L parameter represents the first letter as apposed to just replacing it?
I found the following on MDN but I still don’t quite understand.
You can specify a function as the second parameter. In this case, the function will be invoked after the match has been performed. The function’s result (return value) will be used as the replacement string. (Note: the above-mentioned special replacement patterns do not apply in this case.) Note that the function will be invoked multiple times for each full match to be replaced if the regular expression in the first parameter is global.
instead of with just a pattern you can call the replace method with a function. In this case what’s inside the round parenthesis is not captured, the other part of the regex pattern outside of the round parenthesis is what is being replaced. in total it is “find the first non space character (\S) found at the beginning of the string (^) or after a space character (\s) and replace it with its upper case version”, as the regex has the g flag this is done for all the characters that match the pattern
for debugging I would need to be at my computer, I can’t right now
the documentation will tell you what is being passed in the callback function, and what the method does with the returned value. there is no special syntax that tell a function or method what to do, you will just have to find their behaviour reading about them
in this case what is passed in the callback function is what is being matched by the regex pattern, and the returned value is substituted to that
Thanks @ILM that makes perfect sense. Further reading into MDN explains this.
You can specify a function as the second parameter. In this case, the function will be invoked after the match has been performed. The function’s result (return value) will be used as the replacement string. (Note: the above-mentioned special replacement patterns do not apply in this case.) Note that the function will be invoked multiple times for each full match to be replaced if the regular expression in the first parameter is global.
The arguments to the function are as follows:
Possible name
Supplied value
match
The matched substring.
p1, p2, ...
The n th string found by a parenthesized capture group, provided the first argument to replace() was a RegExp object. (Corresponds to $1 , $2 , etc. above.) For example, if /(\a+)(\b+)/ , was given, p1 is the match for \a+ , and p2 for \b+ .
offset
The offset of the matched substring within the whole string being examined. (For example, if the whole string was 'abcd' , and the matched substring was 'bc' , then this argument will be 1.)
string
The whole string being examined.
The only think I’m still unsure of is why my updated solution wont pass the tests…
@ILM I opened up the browser console and saw a reference error for i being not defined in the for loop. It passed the test by adding var i = 0 instead of i = 0. I understand the error and corrected it but I’m unsure why it sprung. In the past I have never had any issues by not defining i in a for loop. Is it because I reference i within in the loop?