How to correct two initial capitals using JavaScript? - javascript

How to correct the second capital letter of each word into lower case after entering the third letter in lower case?
Example:
"INput" will be corrected into "Input" (since the first and second letter are capital letters)
"INP" will not be corrected.
A function that converts a string would suffice:
function autoCorrect(input) {
return "corrected input";
}
My question is different to existing posts like
Using Javascript, how to capitalize each word in a String excluding
acronyms
Is there a way to ignore acronyms in a title case method
Convert string to Title Case with JavaScript
I don't want to convert a string to title case in such a way that every new word begins with a capital(uppercase) letter but correct two consecutive upper case letters at the beginning of each word.
This seems to work, even if it is not the most elagant solution. Suggestions for improvement are welcome.
String.prototype.isUpperCase = function() {
return this.toString() === this.toUpperCase();
}
var str = "SOme Text THat NO YEs END";
var str2 = str[0] || '';
for (var i = 0; i < str.length; i++) {
const next1 = str[i + 1] || '';
const next2 = str[i + 2] || '';
if (str[i].isUpperCase() && next1.isUpperCase() && !next2.isUpperCase()) {
str2 += str[i+1].toLowerCase() || '';
} else {
str2 += str[i+1] || '';
}
}
console.log(str2);

It sounds like a regular expression is what you need.
The following regular expression matches word characters is in the range A-Z (ie. English uppercase) if that uppercase character is preceded by another word character at the start of a word (negative lookahead assertion (?<=\b\w)) and if that uppercase character is succeeded by one or more lowercase English word characters (lookahead assertion (?=[a-z]+)).
Does this do what you want?
const PATTERN = /(?<=\b\w)([A-Z])(?=[a-z]+)/gu
const fix = (s) =>
s.replaceAll(PATTERN, (_, match) => match.toLowerCase())
console.log(fix('As I aPproached the IBM building, I was asked for ID. Note ALSo.')) // 'As I approached the IBM building, I was asked for ID. Note ALSo.'

Just remove the first two lines, (improvement)
var str = "SOme Text THat NO YEs END";
var str2 = str[0] || '';
for (var i = 0; i < str.length; i++) {
const next1 = str[i + 1] || '';
const next2 = str[i + 2] || '';
if (str[i].isUpperCase() && next1.isUpperCase() && !next2.isUpperCase()) {
str2 += str[i+1].toLowerCase() || '';
} else {
str2 += str[i+1] || '';
}
}
console.log(str2);

Related

I need to transform a short piece of code that adds gaps to a phrase and have no idea how to do it

I have this piece of code that adds some gaps into a word/phrase like this:
"I drove everywhere by car" > "I d_o_e e_e_y_h_r_ _y c_r_"
How can it be transformed so it would to a result that is a little different:
"I drove everywhere by car" > "I d___e e___y___r_ b_ c__"
The difference is that it would show the first letter of every word, then make a 3-letter gap, and, if the word is long enough, show the 5th letter, another 3-letter gap and so on.
The piece of code:
var str = document.getElementById("dropped-v").innerHTML;
letters = '';
for (var i = 0, len = str.length; i < len; i++) {
if (i % 2 != 0 && str[i] != ' ') {
letters += '<span class="hint">_</span>';
}
else {
letters += str[i];
}
}
document.getElementById("dropped-v").innerHTML = letters;
Here's one way to do it for simple sentences without periods. You can add period support and HTML injection as needed.
let MASK = '_';
function obfuscate_word(word) {
const letters = [...word];
const mask_letters = letters.map((letter, i) => i % 4 == 0 ? letter : MASK);
return mask_letters.join('');
}
function obfuscate_sentence(sentence) {
const words = sentence.split(' ');
const mask_words = words.map(word => obfuscate_word(word));
return mask_words.join(' ');
}
const s = "I drove everywhere by car"
console.log(s);
console.log(obfuscate_sentence(s));
If you want to, you can replace the MASK and get/set your HTML something like this:
MASK = '<span class="hint">_</span>';
const e = document.getElementById("dropped-v");
e.innerHTML = obfuscate_sentence(e.innerHTML);
This assumes that the inner HTML of the dropped-v element is a simple sentence (and not a previously-obfuscated sentence that includes markup, for example).

Removing last vowels from every word in a sentence javascript

Write a function that removes the last vowel in each word in a sentence.
Examples:
removeLastVowel("Those who dare to fail miserably can achieve greatly.")
➞ "Thos wh dar t fal miserbly cn achiev gretly."
removeLastVowel("Love is a serious mental disease.")
➞ "Lov s serios mentl diseas"
removeLastVowel("Get busy living or get busy dying.")
➞ "Gt bsy livng r gt bsy dyng"
What I am doing is
function sumDigProd(arr) {
let ans = arr.split(" ");
let array = [];
for (i = 0; i < ans.length; i++) {
for (j = 0; j < ans[i].length; j++) {
var vowelAtLast;
if (
ans[i][j].toLowerCase() == "a" ||
ans[i][j].toLowerCase() == "e" ||
ans[i][j].toLowerCase() == "i" ||
ans[i][j].toLowerCase() == "o" ||
ans[i][j].toLowerCase() == "u"
) {
vowelAtLast = ans[i][j];
}
}
var idex = ans[i].lastIndexOf(vowelAtLast);
console.log(idex,ans[i],ans[i][idex]);
ans[i].replace(ans[i][idex],'')
array.push(ans[i])
console.log(ans)
}
console.log(ans)
return array.join(" ");
}
console.log(sumDigProd("youuo goalo people."));
Here, console.log(idex,ans[i],ans[i][idex]); gives me the correct output for example:
4 "youuo" "o"
But now when I try to do:
ans[i].replace(ans[i][idex],'')
console.log(ans)
I get
["youuo", "goalo", "people."]
again instead i should get
["youu", "goalo", "people."]
after the first time loop runs... and then at last I get the output as
["youu", "goal", "peopl."]
as per the problem but I get
["youuo", "goalo", "people."]
why are no changes made by the replace method here?
A problem is that
ans[i].replace(ans[i][idex], '')
will only replace the first occurrence of whatever character ans[i][idex] is. Eg
aza
would result in
za
Another issue is that you must use the return value of .replace, else it'll go unused and be irrelevant; you'd want something like
ans[i] = ans[i].replace(ans[i][idex], '')
instead, so that the item at that index in the array is properly reassigned.
But it would probably be easier to use a regular expression: match a vowel, followed by capturing zero or more non-vowels in a capture group, with lookahead matching a space or the end of the string. Then replace with the first capture group, thereby removing the last vowel:
const sumDigProd = str => str.replace(
/[aeiou]([^aeiou]*?)(?= |$)/gi,
'$1'
);
console.log(sumDigProd("youuo goalo people."));
[aeiou]([^aeiou]*?)(?= |$) means:
[aeiou] - Any vowel
([^aeiou]*?) - Match and capture:
[^aeiou]*? Any non-vowel, lazily (capture group), up until
(?= |$) - lookahead matches a space or the end of the string
Then
'$1' - Replace with the capture group
To change your original code, identify the last index of a vowel by iterating from the final index of the string and going backwards. When one is found, reassign the string at ans[i] and .sliceing the portions behind and in front of the found vowel:
function sumDigProd(arr) {
let ans = arr.split(" ");
for (i = 0; i < ans.length; i++) {
for (j = ans[i].length - 1; j >= 0; j--) {
if (
ans[i][j].toLowerCase() == "a" ||
ans[i][j].toLowerCase() == "e" ||
ans[i][j].toLowerCase() == "i" ||
ans[i][j].toLowerCase() == "o" ||
ans[i][j].toLowerCase() == "u"
) {
ans[i] = ans[i].slice(0, j) + ans[i].slice(j + 1);
// go to next word
break;
}
}
}
return ans.join(' ');
}
console.log(sumDigProd("youuo goalo people."));

Alternate capitalisation in a string

I would like to create a function which alternates letter capitalisation. For example, Hello World would become HeLlO wOrLd. The first letter of the string must always be capitalised.
Here is the code I have written:
function alternatingCaps(str) {
let alternate = str.charAt(0).toUpperCase();
for(let i = 1; i < str.length; i++) {
let previousChar = str.charAt(i - 1);
if(previousChar === previousChar.toUpperCase())
alternate += str.charAt(i).toLowerCase();
else if(previousChar === previousChar.toLowerCase())
alternate += str.charAt(i).toUpperCase();
}
return alternate;
}
I declared the alternate variable with the capitalised first character of the supplied string. I then loop through the rest of the string and check if the character preceding the current iteration is uppercase or lowercase; whichever it is, the current letter will become the opposite.
However, this does not have the desired outcome. Here are a couple of tests and their corresponding results:
console.log(alternatingCaps('hello world'));
// Output: "HELLO wORLD"
console.log(alternatingCaps('jAvaScrIPT ruLEZ'));
// Output: "JAvAScRIpt rULez"
How do I fix my function?
let s = 'hello there this is a test';
s = s.split('').map( (letter,i) => (i % 2) == 0 ? letter.toUpperCase() : letter.toLowerCase() ).join('')
console.log( s );
Update: if you want to ignore but preserve the spaces, then here is another solution, albeit a little screwy. It doesn't just ignore spaces, it only operates on letters matching the regular expression.
let s = 'hello there this is a test';
let ul = false;
s = s.split('').map(letter => letter.match(/[a-zA-Z]/) != null ? (ul = ! ul, ul ? letter.toUpperCase() : letter.toLowerCase()) : letter).join('');
console.log( s );
Simplest solution i can think of is using for loop and Remainder operator.
let alterNate = (input) => {
let str = ''
let last = 'L'
for(let i=0; i<input.length; i++){
if( /[a-z]/ig.test(input[i]) ) {
if(last==='L'){
str+= input[i].toUpperCase()
last = 'U'
} else{
str+= input[i].toLowerCase()
last = 'L'
}
} else {
str+=input[i]
}
}
return str;
}
console.log(alterNate('hello world'))
My solution uses RegEx replace to achieve the expected result:
function alternatingCaps(str) {
return str.replace(/\w(.|$)/g, s => s[0].toUpperCase() + (s[1] ? s[1].toLowerCase() : ''));
}
console.log(alternatingCaps('hello world'));
console.log(alternatingCaps('jAvaScrIPT ruLEZ'));
There are two things to pay attention for:
\w(.|$) - This regular expression captures a word character (\w) and any other following char. The (.|$) address for an odd number of characters. We're basically capturing the characters in pairs here;
s => s[0].toUpperCase() + (s[1] ? s[1].toLowerCase() : '') - This replacing function does the rest of the job:
s[0].toUpperCase() - It takes s[0] and changes it to uppercase;
(s[1] ? s[1].toLowerCase() : '') - And it takes s[1], if it exists, and changes it to lowercase.
Here is the sample regex for alternating case
[A-Z]([a-z][A-Z])*[a-z]?
https://regex101.com/r/UPHRUk/1

Finding the index to a non-specified character

Let's say for example I have a string
thisIsThisTuesday Day
I want to find the index of all the capital letters, test if there is a space before it, and if not insert one. I would need the index of each one.
At least from what I can see indexOf(String) will only produce the index of the first occurance of the character T/t
This :
for(i=0;i<str.length;i++){
let char=str[i];
if(isNaN(char*1)&&char==char.toUpperCase()){
y=str.indexOf(char);
console.log(char,y)
}
}
would produce the capital letters, and their indexes but will only display the first occurrence of the character in question. I feel pretty confident that the part I am missing is a for() loop in order to move the index iteration..but it escapes me.
Thank you in advance!
You can use a regex:
It matches any non-whitespace character followed by a capital letter and replaces it by the two characters with a space between.
const str = "thisIsThisTuesday Day";
const newstr = str.replace(/([^ ])([A-Z])/g, "$1 $2");
console.log(newstr);
You can use the following regular expression:
/(?<=\S)(?=[A-Z])/g
The replace will insert spaced between characters which are non-space followed by a capital letter.
See example below:
let str = "thisIsThisTuesday Day";
const res = str.replace(/(?<=\S)(?=[A-Z])/g, ' ');
console.log(res);
Note: As pointed out ?<= (positive lookbehind) is currently not be available in all browsers.
Actually, the String.indexOf function can take a second argument, specifying the character it should start searching from. Take a look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
But, if you just want to find all capital letters and prefix them with a space character, if one is not found, there are many approaches, for example:
var str = "thisIsThisTuesday Day";
var ret = '';
for (var i=0; i<str.length; i++) {
if (str.substr(i, 1) == str.substr(i, 1).toUpperCase()) {
if ((i > 0) && (str.substr(i - 1,1) != " "))
ret += " ";
}
ret += str.substr(i,1);
}
After running this, ret will hold the value "this Is This Tuesday Day"
You could iterate over the string and check if each character is a capital. Something like this:
const s = 'thisIsThisTuesday Day';
const format = (s) => {
let string = '';
for (let c of s) {
if (c.match(/[A-Z]/)) string += ' ';
string += c;
}
return string;
};
console.log(format(s));
Or alternatively with reduce function:
const s = 'thisIsThisTuesday Day';
const format = (s) => s.split('').reduce((acc, c) => c.match(/[A-Z]/) ? acc + ` ${c}` : acc + c, '');
console.log(format(s));

Why does my Javascript trim Function not work?

I am using this function to build a pig latin translator and seem to have everything figured out except for the .trim() part. What should I do different?
function ParseText()
{
var myText = "asdf\n hat\n cat dog\n apple";
var lines = myText.split("\n");
var results = "";
for (var i = 0, len = lines.length; i < len; i++) {
lines[i].trim();
var words = lines[i].split(" ");
for (var j = 0, lenght = words.length; j < lenght; j++) {
var word = words[j];
if (word.charAt(0) == "a" || word.charAt(0) == "e" || word.charAt(0) == "i" || word.charAt(0) == "o" || word.charAt(0) == "u" || word.charAt(0) == "y")
{
results = results + word + "ay ";
}else {
var mutated = word.substring(1, word.length);
mutated = mutated + word.charAt(0)+ "ay ";
results = results + mutated;
}
}
results = results + "\n";
}
return results;
}
On the line lines[i].trim(); nothing seems to happen. the whitespace still becomes a \n item in the split array.
What should I change to remove the whitespace?
lines[i].trim(); does NOT modify the current string (see the doc here). It returns a new string.
If you want to trim the current string, then you need to do this:
lines[i] = lines[i].trim();
As per comments, here's very basic version of pig latin using regex that works with lowercase strings but it can be adjusted to handle mixed lower and upper case:
function pigLatin(str) {
return str
.toLowerCase() // make sure string is lowercase
.replace(/\b[aeiuo]\w+\b/g, '$&way') // starts with vowel
.replace(/\b([^aeiou\s])(\w+)\b/g, '$2$1ay'); // starts with consonant
}
// Example:
var str = 'hello world egg plant yellow';
console.log(pigLatin(str)); //=> "ellohay orldway eggway lantpay ellowyay"

Categories

Resources