capitalizing only first letter in a contraction - javascript

My challenge is to capitalize the first letter of each word in a string while making sure all the other letters are lowercase. I have spent more hours then I'm willing to admit on this and my code is shown below. It's about 95% complete.
It's only flaw is that it returns contractions like "I'm" as "I'M". For some reason it sees contractions as two separate words. I tested this my putting a console.log immediately after the step that capitalizes the first letter (I have commented it out in the example). it returns that it is capitalizing both "I" and "M" in the same step. How do I get get it change only the "I"?
function titleCase(str) {
str = str.toLowerCase(); //make everything lowercase
str = str.split(" "); //make the string to array
for(i = 0; i < str.length; i++){
var strItem = str[i]; //take item in array
strItem = strItem.replace(/\b./g, function(m){ return m.toUpperCase(); }); //capitalize it
//console.log(strItem);
str[i] = strItem; //put changed item back into array
}
str = str.join(" "); //turn array back into string
return str;
}
titleCase("I'm a little tea pot");
Thank you for your time.

Your problem seems to be that you are using a global match in your replacer expression.
Remove the g.
function titleCase(str) {
str = str.toLowerCase(); // Make everything lowercase
str = str.split(/\s+/); // Make the string to array
for (var i = 0; i < str.length; i++) {
var strItem = str[i]; // Take item in array
strItem = strItem.replace(/\b./,
function(m) {
return m.toUpperCase(); // Capitalize it
}
);
str[i] = strItem; // Put changed item back into array
}
return str.join(" "); // Turn array back into string
}
document.body.innerHTML = titleCase("I'm a little tea pot");
Simplified
You can create a capitalCase function and use it as the mapping (callback) function for each word.
function titleCase(str) {
return str.split(/\s+/).map(captitalCase).join(' ');
}
function captitalCase(str) {
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
}
document.body.innerHTML = titleCase("I'm a little tea pot");
Preserve White-Space
If you want to preserve white-space, you can replace all sequences non-white-space characters with their respective capitalCase equivalent.
function titleCase(str) {
return str.replace(/(\S+)/g, function(m) {
return captitalCase(m);
});
}
function captitalCase(str) {
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
}
document.body.innerHTML = titleCase("I'm a little \n tea pot");
body {
white-space: pre;
}

What I suggest, is that you use <string>.charAt(<index>) to get the first letter of a string, and that <string>.slice(<index>) can give you a portion of a string.
Hint: After taking each word, you could take the first letter using charAt(), uppercase it, then take the rest slice of your string and lowercase it.
UPDATE:
Answer:
function upperFirstLetterInWords(str) {
var totalString = "";
//Take words from sentence -
//Use regex /\s+/g for many spaces in sentence.
var words = str.split(" ");
//Take each word...
//Using for loop as we have an array and it is
//more efficient than foreach loop or lambda.
for(var i = 0; i < words.length; ++i) {
//Make your changes here.javascript:;
totalString += words[i].charAt(0).toUpperCase() +
words[i].slice(1).toLowerCase() +
" ";
}
//Remove last space.
return totalString.trim();
}
console.log(upperFirstLetterInWords("I'm A LitTle TEa POt."));

Out of curiosity, I wanted to see if I could come up with an alternative javascript solution without using regex:
var selectedParagraph = document.getElementsByTagName('p')[1];
var textUC = [];
function toTitleCase(element) {
var textLC = element.innerHTML.toLowerCase().split(' ');
for (var i = 0; i < textLC.length; i++) {
textUC[i] = textLC[i].substr(0,1).toUpperCase() + textLC[i].substr(1);}
element.innerHTML = textUC.join(' ');
}
window.onload = toTitleCase(selectedParagraph);
<p>I'm a little tea pot</p>
<p>I'm a little tea pot</p>

Related

Function to capitalize first and last letter of each word not working

I created a function that given any string will return the string with the first and last letter of each word capitalized. So far it works in some words, not on others, can someone help me figure out why?
function Capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
//For every word
for (let j = 0; j < spl[i].length; j++) {
//For every letter in each word
var word = spl[i];
var size = spl[i].length;
var firstLetterCapital = word.replace(word[0], word[0].toUpperCase()); //Creates new array
var LastLetterCapital = firstLetterCapital.replace(
word[size - 1],
word[size - 1].toUpperCase()
);
}
words.push(LastLetterCapital);
}
console.log(words.join(" "));
}
Capitalize("hello there");
It works when I type : Capitalize("my name is john smith"), but not with Capitalize("hello there")
I know it's a complete mess and probably a very bad way to do it, but I started programming a month ago so give me a break :)
#symlink has already explained why it is "HellO ThEre" instead of "Hello TherE". He also has given a solution to explicitly target first and last character of the string. I have accomplished not much different than already posted by members, except for .. "may be" a little more explanation.
You can break the entire problem in these four steps.
Get all the words into an array.
Create a function, that takes each word and targets first and last character, changes it and returns the changed word.
Apply a mapping step using the function created above (in step 2) to the entire array of words (obtained in step 1).
Join the transformed array, obtained in step 3, using a blank space as a separator.
I have written two functions that accomplish this task. I am sorry for long name of functions. It helps me keep track of things in a complex program (especially when I am in a hurry!).
Step 2 function
function Capitalize_FirstAndLast_One_Word(word){
// Split the string in array for easy access/manipulation by indexing
Split_String = word.split("")
// Target the first word
Split_String[0] = Split_String[0].toUpperCase();
// Target the last word
Split_String[Split_String.length - 1] = Split_String[Split_String.length - 1].toUpperCase();
// Join the array into a single word
Joined_Back = Split_String.join("")
return Joined_Back;
}
Step 1, 3 and 4 function
function Capitalize_Entire_String(str){
Regular_Exp = new RegExp(/\w+/g);
//Below is step 1
MatchedArray = str.match(Regular_Exp);
//Below is step 3
ConvertedArray = MatchedArray.map(Capitalize_FirstAndLast_One_Word);
// Below is step 4
ReturnedString = ConvertedArray.join(" ");
console.log(ReturnedString);
return ReturnedString;
}
Now you have everything. You can use the function like below.
Capitalize_Entire_String("hello there");
Capitalize_Entire_String("hello there this is a test");
Hope this helps. I am sorry if this turned out to be a redundant answer for you.
Reason your code don't work is the use of replace(). replace() will always replace the first character found.
There is absolutely no reason to run a nested loop. You can achieve this using a single loop.
function cap(str){
let spl = str.split(' ');
for(let i = 0; i < spl.length; i++){
let temp = spl[i];
temp = temp[0].toUpperCase() + temp.slice(1)
temp = temp.slice(0,-1) + temp[temp.length - 1].toUpperCase();
spl[i] = temp;
}
return spl.join(' ');
}
console.log(cap("a quick brown fox"))
An easier way is to use map() and template strings.
const cap = str => str
.split(' ')
.map(x => (
x.length === 1 ?
x.toUpperCase() :
`${x[0].toUpperCase()}${x.slice(1,-1)}${x[x.length -1].toUpperCase()}`)
)
.join(' ')
console.log(cap("a quick brown fox"))
To simplify the function, you could split the string into an array, map each word to the desired format, and join it together into a string again.
function Capitalize(str){
return str.split(" ").map((word) => word.charAt(0).toUpperCase() +
(word.length > 2 ? word.substring(1, word.length - 1) : "") +
(word.length > 1 ? word.charAt(word.length - 1).toUpperCase() : "")).join(" ");
}
console.log(Capitalize("i want to capitalize first and last letters"));
Congrats on starting out programming...
You can use this to achieve what you want to do
function capitalizeFirstAndLastLetters (str) {
const words = str.split(" "); // Split the string into words
const modified = [];
for (const word of words) {
if (word.length <= 2) {
modified.push(word.toUpperCase()); // If the word less than 3 characters, the whole word is capitalized
continue;
}
var firstCapital = word[0].toUpperCase(); // word[0] gets the first index of the string (I.e. the first letter of the word)
var lastCapital = word.slice(-1).toUpperCase(); // The slice function slices a portion of the word. slice(-1) gets the last letter
var middlePart = word.slice(1, -1); // slice(1, -1) means start slicing from the second index (I.e. 1) and ignore the last index
modified.push(firstCapital + middlePart + lastCapital);
}
return modified.join(" "); // Join each element in the modified array with a space to get the final string with each words first and last letters capitalized
}
capitalizeFirstAndLastLetters("hello there I am a boy"); // "HellO TherE I AM A BoY"
Try this, it worked for hello world because I guess you want the outcome to be HellO TherE right?:
function capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
//For every word
let changedWord = "";
for (let j = 0; j < spl[i].length; j++) {
//For every letter in each word
if(j == 0 || j == spl[i].length - 1) {
changedWord += spl[i][j].toUpperCase();
} else {
changedWord += spl[i][j].toLowerCase();
}
}
words.push(changedWord);
console.log(words);
}
console.log(words.join(" "));
}
capitalize("hello there");
ALSO: Make your functions name start with lowercase letter. Thats just how it is. Starting with uppercase letters usually are Classes. Just a quick tip
Maybe this does what you want, don't want to change much from your code:
function Capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
var word = spl[i];
var firstCapital = word[0].toUpperCase(); // get first character after capitalizing
var lastCapital = word.slice(-1).toUpperCase(); // get last character after capitalizing
var midOriginal = word.slice(1, -1);
words.push(firstCapital + midOriginal + lastCapital) // concat 3 parts
}
console.log(words.join(" "));
}
Capitalize("hello there");
This expression:
var LastLetterCapital = firstLetterCapital.replace(
word[size - 1],
word[size - 1].toUpperCase()
);
Is replacing the first occurrence of the character "e" in "There" with an uppercase "E".
Explanation
The replace() function first translates the first param: word[size - 1] to the literal character "e", then replaces the first occurrence of that character with the uppercase "E", resulting in the string "ThEre".
Solution
Use a regular expression as your first parameter instead, to ensure that the last character is targeted, regardless of whether or not that same character shows up anywhere else in the word:
var LastLetterCapital = firstLetterCapital.replace(/.$/, word[size - 1].toUpperCase());
function Capitalize(str) {
var spl = str.split(" ");
var words = [];
for (let i = 0; i < spl.length; i++) {
//For every word
var word = spl[i];
var size = spl[i].length;
for (let j = 0; j < size; j++) {
//For every letter in each word
var firstLetterCapital = word.replace(word[0], word[0].toUpperCase()); //Creates new array
var LastLetterCapital = firstLetterCapital.replace(/.$/, word[size - 1].toUpperCase());
}
words.push(LastLetterCapital);
}
console.log(words.join(" "));
}
Capitalize("hello there");
This should do the trick:
function Capitalize(str) {
return str.replace(/(\b\w|\w\b)/g, l => l.toUpperCase())
}
console.log(Capitalize('i want to be capitalized in a rather strange way'))
Explanation:
In the regular expression /(\b\w|\w\b)/g, \b means "word boundary" and \w means "word character", so (\b\w|\w\b) matches a word boundary followed by a word character OR a word character followed by a word boundary (i.e. the first and last character of words).
The matches of this expression are then passed to the inline function l => l.toUpperCase() (which itself is the second argument to replace) that capitalizes the passed letter.
the string type is immutable, so why don't you try to convert the string to an array like y = word.split('') and do y[0] = word.charAt(0).toUpperCase() and then convert back to string with y.join('')

What's wrong with my code? first letter of each word should capitalized

function titleCase(str) {
var str1 = str.match(/\S+\s*/g);
var str2;
for(var i = 0; i < str1.length; i++){
str2 = str1[i].toLowerCase().replace(str1[i].charAt(0), str1[i].charAt(0).toUpperCase());
}
return str2.join(' ');
}
titleCase("I'm a little tea pot");
What's wrong with my code? str2.join is not a function
Easiest way to go about this is to split the string on every space, then set the first letter of each element in the array to the capitalized version of the letter and join it back.
What you are doing is assigning the value of the result to str2, having a string type rather than an array, that is why join is not working for you.
function titleCase(str) {
const words = str.split(' ');
for (let i = 0; i < words.length; i++) {
words[i] = words[i][0].toUpperCase() + words[i].slice(1);
}
return words.join(' ');
}
A slightly different variant with some ES6 favor to it:
const titleCase = str => {
const result = [];
for (const word of str.split(' ')) {
result.push(word[0].toUpperCase() + word.slice(1));
}
return result.join(' ');
};
If you want to ensure space characters such as tabs, newlines etc. work, you can split using your regex or replace all whitespace characters with spaces as a first step, e.g.:
const words = str.replace(/\s/g, ' ').split(' ').filter(word => word !== '');
function titleCase(str) {
var str1 = str.match(/\S+\s*/g);
var str2 = [];
for(var i = 0; i < str1.length; i++){
str2[i] = str1[i].replace(str1[i].charAt(0), str1[i].charAt(0).toUpperCase());
}
return str2.join(' ');
}
titleCase("I'm a little tea pot");
This is a simple solution to your problem. However, there are many ways to get the same result this is one of them.
function capitalize(str) {
let str2 = str[0].toUpperCase();
return str.replace(str[0], str2);
}

Capitalize the first letter of each string [duplicate]

This question already has answers here:
Convert string to Title Case with JavaScript
(68 answers)
Closed 5 years ago.
I've been trying to capitalize the first letter of each word in a string, but it says TypeError: Cannot assign to read only property '0' of string 'i' . My logic looks fine but surely the way I'm doing this is not right. Any suggestions.
function titleCase(str) {
str = str.toLowerCase();
var word = str.split(" ");
// console.log(word[0][0]);
for (var i = 0; i < word.length - 1; i++) {
word[i][0] = word[i][0].toUpperCase();
}
console.log(word);
return word;
}
titleCase("I'm a little tea pot");
Try like so: (see comments in code)
function titleCase(str) {
str=str.toLowerCase();
var word = str.split(" ");
for (var i=0; i < word.length; i++) { // you don't need -1 here as you had
word[i] = word[i].charAt(0).toUpperCase() + word[i].slice(1); // see changes in this line
}
console.log(word);
return word;
}
titleCase("I'm a little tea pot");
Strings have a replace method that accepts a function:
var s = 'foo bar fum i am sparticus 23!!';
console.log(s.replace(/\b\w/g, function(s){return s.toUpperCase()}));
You can directly convert your string into what you want by inbuilt array function.
Using map function you will get it directly no need to run for loop.
("I'm a little tea pot")
.split(" ")
.map(function(d){
return d[0].toUpperCase()+d.substring(1,d.length)
}).join(" ")
You can combine split and map functions to achieve this.
function titleCase(str) {
return str.toLowerCase().split(" ").map(function(word) {
var _word = word.split("");
_word[0] = _word[0].toUpperCase();
return _word.join("");
}).join(" ");
}
console.log(titleCase("I'm a little tea pot"));
You can use map function to create an array of modified words and join to recreate the string
function titleCase(str) {
str = str.toLowerCase();
var word = str.split(" ");
var x = word.map(function(item) {
return item.charAt(0).toUpperCase() + item.substring(1, item.length);
}).join(" ");
return x
}
console.log(titleCase("I'm a little tea pot"));
Using only CSS
#test {
text-transform: capitalize
}
<div id="test"> I'm a little tea pot</div>
With split, array map and reduce:
var str = "I'm a little tea pot";
var res = str.split(" ")
.map(word => word.charAt(0).toUpperCase() + word.substr(1))
.reduce((m, o) => { m = m + " " + o; return m }, "")
console.log(res);
Join can be also used instead of reduce:
var str = "I'm a little tea pot";
var res = str.split(" ")
.map(word => word.charAt(0).toUpperCase() + word.substr(1))
.join(" ");
console.log(res);

The mission is to turn each word's first letter into capital (Javascript)

The code below doesn't work why?
function titleCase(str){
var newStr = str.split(" "); //split string turn it into seperated words[]
var resutl;
for(vari=0; i < newStr.length; i++){ //iterate all words
var result = newStr[i].charAt(0).toUpperCase +
// find first letter and turn it into capital
newStr[i].subString(1).toLowerCase();
}
return result.join(" ");
}
result in your code is a string, not an array. you cannot join a string.
each iteration of the loop you are replacing the variable result with a new word. you need to initialize a result array [] and push each result onto the array, then join the array after the loop has completed.
The result needs to be an array and also you have some typos in your code, e.g. missing ()
function titleCase(str) {
var newStr = str.split(" ");
var result = [];
for (var i = 0; i < newStr.length; i++) {
result.push(newStr[i].charAt(0).toUpperCase() + newStr[i].substring(1).toLowerCase());
}
return result.join(' ');
}
var str = 'hELLO wORLD';
document.write(titleCase(str));
Try using regular expression
var data = "The mission is to turn each word's first letter into capital";
data = data.replace(/ (.)/g,function(w){return w.toUpperCase()});
drawback :this will not capitalize the first character.
Explode the string on spaces and iterate it with the function below:
function ucfirst(str) {
str += ''; // make sure str is really a string
var f = str.charAt(0).toUpperCase();
return f + str.substr(1);
}
You may try this :
function titleCase(str){
var newStr = str.split(" ");
var result = [];
for(var i=0; i < newStr.length; i++){
result.push(newStr[i].charAt(0).toUpperCase() +
newStr[i].substring(1).toLowerCase());
}
return result.join(' ');
}
Another Approach:
function titleCase(str){
var words = str.split(" ");
return words.map(function(word){
return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
}).join(" ");
}

Find the nth character from an array of words in JavaScript

I'd like to create a function (nthChar) that takes 1 parameter - an array of n words.
The function should concatenate the nth letter from each word to construct a new word which should be returned as a string.
The nth letter should be the 1st from the first word in the array, the second from the second word in the array, the third from the third and so on. So:
nthChar(['I','am','Tom']) should return 'Imm'
Here's my attempt:
function nthChar(words){
for (var i=0; i<words.length; i++) {
return words[i].charAt(words.indexOf(words[i]))
}
}
Which only seems to grab the first letter of the first word. How would I proceed to the other words of the array before concatenation?
With minimal changes to your code, you can do this
function nthChar(arr) {
var str = '';
for (var i=0; i<words.length; i++) {
str = str + words[i][i];
}
return str;
}
str - used to build up the result string
words[i] selects the i'th word ... the second [i] in that statement selects the i'th letter in that word
for example: "Hello World"[6] is W
Bonus: works in IE8 and earlier ...
and, just for the hell of it, void's answer in ES6
var nthChar = arr => arr.map((i, v) => i[v]).join('');
This can be as simple as
function nthChar(words){
var s = "";
for(var i=0;i<words.length;i++){
s+= words[i].charAt(i);
}
return s;
}
Live example: http://jsfiddle.net/11yc79jn/
This is closest to your original solution, and just uses the loop control variable i which is incrementing already as you loop through the words array. Of course, also return after the entire loop has run as well.
function nthChar(arr){
return arr.map(function(i, v){
return i[v];
}).join("");
}
console.log(nthChar(['I','am','Tom']));
So it is returning an array of the characters you want and then it is joining it. Makes sense?
The issue with your code was that you were not concatenating anything to the output. You can access the characters of a string as if it is an array.
Live Fiddle
Your code can be:
function nthChar(words){
var str = "";
for (var i=0; i<words.length; i++) {
str += words[i].charAt(i);
}
return str;
}
Fiddle
Try something like this
function nthChar(words){
var result = "";
for (var i = 0, ln = words.length; i<ln; i++)
result += words[i].charAt(i);
return result;
}

Categories