Please help me. I'm doing exercise and I don't understand what I'm doing wrong if all conditions execute. The task consists in returning the provided string with only the first letter of each word capitalized. My code performs this condition, but It doesn't get me ahead.
function titleCase(str) {
var text = str.toLowerCase();
var arr = text.split(" ");
var txt = " ";
var i;
for(i=0; i < arr.length; i++) {
txt += arr[i][0].toUpperCase() + arr[i].slice(1) + " " ;
}
return txt;
}
titleCase("sHoRt AnD sToUt");
You are adding extra whitespace (var txt = " " should be var text = ''), try this instead:
function titleCase(str) {
var text = str.toLowerCase();
// split on spaces, map over array and return capitalized word and join on space
return text.split(' ').map((word) => {
return word[0].toUpperCase() + word.slice(1);
}).join(' ');
}
alert(titleCase("sHoRt AnD sToUt"));
If your goal is to return the string back with the first letters capitalized, I can see one problem in your output. You should be returning
"Short And Stout"
but instead you return
" Short And Stout "
with a space before and after your string. You can fix this by initializing txt to an empty string rather than a space, and then either trimming the last space off at the end after your loop, or by only adding the space if you aren't on the last element of arr. That is:
var txt = "";
for(var i=0; i < arr.length; i++) {
txt += arr[i][0].toUpperCase() + arr[i].slice(1);
if (i != arr.length - 1) txt += " ";
}
You can use regular expression instead.
function titleCase(txt){
return txt.toLowerCase().replace(/\b\w/g, function(m){return m.toUpperCase();});
}
console.log(titleCase("sHoRt AnD sToUt"));//"Short And Stout"
Some explanation.
// regular expression (RegEx), g for global (else first only)
\b word boundary
\w any word symbol a-z (plus _)
m (function parameter) is match in the string
Related
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('')
I need to capitalize all letters in the beginning of a string, all letters before the first number that appears in the string.
abc123 will be ABC123
abc123def will be ABC123def
First I find the index of the first number in the string:
var index = myString.search(/\d/);
Then I have a for loop where I try to change every letter before that number:
for (var i=0; i<index; i++) {
myString = myString.charAt(i).toUpperCase() + myString.slice(i+1);
}
The problem is that the code removes the letter in the beginning in every loop.
How can I do it better?
Thank you for your help
You can do it by the code below:
var str = "abc23mlk";
var index = str.search(/\d/);
if (index !== -1) {
str = str.slice(0, index).toUpperCase() + str.slice(index);
}
console.log(str);
You can use a regex and a replacer function:
function replace(text) {
return text.replace(/[a-z]+(?=\d)/i, function(match) {
return match.toUpperCase();
});
}
["abc123", "abc123def", "abcd12efgh34ijkl"].forEach(function(test) {
console.log("'" + test + "' becomes '" + replace(test) + "'");
});
The regex /[a-z]+(?=\d)/i looks for the first sequence of letters ([a-z]+) that is immediately followed by a digit ((?=\d) here as a positive look-ahead so it is not matched).
You also do something like
Find the index as how you are doing now
Substring and capitalize
Slice and append
var myString = "abc123"
var index = myString.search(/\d/);
myString = myString.substr(0,index).toUpperCase() + myString.slice(index);
This question already has answers here:
How to remove spaces from a string using JavaScript?
(15 answers)
Looping through array and removing items, without breaking for loop
(17 answers)
Closed 6 years ago.
I created a function to delete the spaces out of a string and return the strings length with out spaces, however the function is deleting more then just the spaces. Also is there a better way of accomplishing this, assuming this function can be fixed.
let string="This string is going to lose characters";
function charLength(str){
let strArray=str.split("");
let output="";
for(let i=0; i < strArray.length; i++){
if(strArray[i]===" "){
strArray.splice(strArray[i],1);
}
else{
output+=strArray[i];
}
}
return output.length // + " " output, if I were to add this you would see its deleting characters
}
charLength(string);//returns "27 Thistringsoingooseharacters", not "33 Thisstringisgoingtolosecharacters"
When you remove a character from the string you'll have to go back one step (i--) st the loop won't skip a character (for(... ; i++)). Like this:
if (strArray[i] === " ") {
strArray.splice(strArray[i], 1);
i--; // ge back one step if we remove one character.
}
Snippet:
let string = "This string is not going to lose characters";
function charLength(str) {
let strArray = str.split("");
let output = "";
for (let i = 0; i < strArray.length; i++) {
if (strArray[i] === " ") {
strArray.splice(strArray[i], 1);
i--;
} else {
output += strArray[i];
}
}
return output;
}
console.log(charLength(string));
If you want to count characters that are not spaces:
Then just make a counter that will count the characters that are not spaces like this:
let string = "This string is not going to lose characters";
function charLength(str) {
let counter = 0; // the counter
for (let i = 0; i < str.length; i++) { // for each character in the string
if(str.charAt(i) !== ' ') // if the character is not a space
counter++; // increment the counter
}
return counter;
}
console.log(charLength(string));
The reason why characters get lost, is because the list is modified inside the loop.
for(let i=0; i < strArray.length; i++){
if(strArray[i]===" "){
strArray.splice(strArray[i],1); // Items are removed here
...
When you remove an character i, the next character will take its place.
You could maybe use the replace function instead like this:
string.replace(/ /gi, "").length
Use regex.
var str = 'This string is going to lose characters';
// The substituted value will be contained in the result variable
const result = str.replace(/\s/g, '');
console.log('Substitution result: ', result.length);
You don't need a regex: str.replace(" ","") is already doing that.
Instead of this line here:
strArray.splice(strArray[i],1);
Try using this:
strArray.splice(strArray[i],0);
Just replaces the 1 with 0
This is much simpler than you are doing. You can just use the .replace() string method which can take a string literal to replace or a regular expression.
function charLength(str){
// Create a new string that is the same as the passed in one, but with the spaces stripped out
// The syntax / / denotes a regular expresion (regEx) object
// The s+ denotes to look for one or more spaces in a row
// The g denotes a global search and replace througout the string
var newStr = str.replace(/\s+/g, "");
console.log("\"" + str + "\" has: " + str.length + " characters.");
console.log("\"" + newStr + "\" has: " + newStr.length + " characters.");
}
charLength("This string is going to lose characters");
You could use eiter a regular expression for filtering space
var string = "This string is going to lose characters",
result = [...string].filter(RegExp.prototype.test.bind(RegExp('[^ ]'))).join('');
console.log(result);
console.log(result.length);
Or just test for space.
var string = "This string is going to lose characters",
result = [...string].filter(a => a !== ' ').join('');
console.log(result);
console.log(result.length);
I'm looking for a regex that will remove all characters that have been repeated in a string. I already solved this using a loop. Just wondering if there is a regex that can do the same.
this is what i have so far:
function onlyUnique(str) {
var re = /(.)(?=.*\1)/g
return str.replace(re, '');
}
This string:
"rc iauauc!gcusa_usdiscgaesracg"
should end up as this:
" !_de"
You can use Array#filter with Array#indexOf and Array#lastIndexOf to check if the element is repeated.
var str = "rc iauauc!gcusa_usdiscgaesracg";
// Split to get array
var arr = str.split('');
// Filter splitted array
str = arr.filter(function (e) {
// If index and lastIndex are equal, the element is not repeated
return arr.indexOf(e) === arr.lastIndexOf(e);
}).join(''); // Join to get string from array
console.log(str);
document.write(str);
well, no idea if regex can do that, but you could work it out using for loop, like:
function unikChars(str) {
store = [];
for (var a = 0, len = str.length; a < len; a++) {
var ch = str.charAt(a);
if (str.indexOf(ch) == a && str.indexOf(ch, a + 1) == -1) {
store.push(ch);
}
}
return store.join("");
}
var str = 'rc iauauc!gcusa_usdiscgaesracg';
console.log(unikChars(str)); //gives !_de
Demo:: jsFiddle
Your regex searches pairs of duplicated characters and only removes the first one. Therefore, the latest duplicate won't be removed.
To address this problem, you should remove all duplicates simultaneously, but I don't think you can do this with a single replace.
Instead, I would build a map which counts the occurrences of each character, and then iterate the string again, pushing the characters that appeared only once to a new string:
function onlyUnique(str) {
var map = Object.create(null);
for(var i=0; i<str.length; ++i)
map[str[i]] = (map[str[i]] || 0) + 1;
var chars = [];
for(var i=0; i<str.length; ++i)
if(map[str[i]] === 1)
chars.push(str[i]);
return chars.join('');
}
Unlike indexOf, searches in the hash map are constant on average. So the cost of a call with a string of n characters will be n.
If you want to do it with a regex, you can use your own regex with a callback function inside a replace.
var re = /(.)(?=.*\1)/g;
var str = 'rc iauauc!gcusa_usdiscgaesracg';
var result = str;
str.replace(re, function(m, g1) {
result = result.replace(RegExp(g1.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), '');
});
document.getElementById("r").innerHTML = "'" + result + "'";
<div id="r"/>
The idea is: get the duplicated character, and remove it from the input string. Note that escaping is necessary if the character might be a special regex metacharacter (thus, g1.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") is used).
Another idea belongs to Washington Guedes in his deleted answer, I just add my own implementation here (with removing duplicate symbols from the character class and escaping special regex chars):
var s = "rc iauauc!gcusa_u]sdiscgaesracg]";
var delimiters= '[' + s.match(/(.)(?=.*\1)/g).filter(function(value, index, self) { // find all repeating chars
return self.indexOf(value) === index; // get unique values only
}).join('').replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + ']'; // escape special chars
var regex = new RegExp(delimiters, 'g'); // build the global regex from the delimiters
var result = s.replace(regex, ''); // obtain the result
document.getElementById("r2").innerHTML = "'" + result + "'";
<div id="r2"/>
NOTE: if you want to support newline symbols as well, replace . with [^] or [\s\S] inside the regex pattern.
function onlyUnique(str) {
// match the characters you want to remove
var match = str.match(/(.)(?=.*\1)/g);
if (match) {
// build your regex pattern
match = '[' + match.join('') + ']';
}
// if string is already unique return the string
else {
return str
}
// create a regex with the characters you want to remove
var re = new RegExp(match, 'g');
return str.replace(re, '');
}
Having trouble coming up with code doing this.
So for example here is my string.
var str = "Hello how are you today?";
How would I manipulate this string to return the position of the first letter of each word using a loop?
this will give you the result with less complicated code and a single loop
function foo(str) {
var pos = [];
var words = str.split(' ');
pos.push(1);
var prevWordPos;
for (var i = 1; i < words.length; i++) {
prevWordPos = pos[i - 1] + words[i - 1].length;
pos.push((str.indexOf(words[i], prevWordPos) + 1));
}
return pos;
}
You should search for a question before asking it in case it's already been asked and answered.
Get first letter of each word in a string, in Javascript
You can use a regexp replace passing a function instead of a replacement string, this will call the function for each match:
str.replace(/[^ ]+/g, function(match, pos) {
console.log("Word " + match + " starts at position " + pos);
});
The regexp meaning is:
[^ ]: anything excluding space
+: one or more times
"g" option: not only first match, but each of them
in other words the function will be called with sequences of non-spaces. Of course you can define what you consider a "word" differently.
Here is a Solution with two Loops, i hope that is close enough ;)
var starts = [];
var str = "How are you doing today?";
//var count = 0;
var orgStr = str;
while (str.indexOf(" ") > 0) {
if (starts.length > 0) {
starts.push(starts[starts.length - 1] + str.indexOf(" ") +1);
} else {
starts.push(1);
starts.push(str.indexOf(" ") +2);
//alert(str);
}
str = str.substring(str.indexOf(" ") + 1);
}
for (var i = 0; i < starts.length; i++) {
alert(starts[i] + ": " + orgStr.substring(starts[i]-1,starts[i]))
}
Easiest would be to search a regular expression \b\w and collect match.start() match.index for each match. Loop while there's matches.
EDIT: wrong language. lol.