let message = "heY, WHAt are you dOING?";
let count_changes = 0;
let isLetter = (letter) => {
if (('a'<=letter && letter >='z') || ('A'<=letter && letter >='Z')) {
return letter;
} else {
return -1;
}
}
for(let i = 0; i <= message.length; i++) {
if (isLetter(i) && message[i].toLowerCase()) {
message[i].toUpperCase();
count_changes++;
console.log(message[i].toLowerCase());
}
else if (isLetter(i) && message[i].toUpperCase()) {
message[i].toLowerCase();
count_changes++;
}
else {
console.error('Bad stirng');
}
}
Hello, I want to use the function isLetter to check the string message every character and when i use isLetter in the for loop to check in the if statement whether i is a Letter or not and also if its Lowercase letter later to when there is a change to Uppercase i increment count_changes++. Again with the second if statement if also i is Letter and in this case Uppercase letter then if change to lowercase letter to increment the count_changes++ so the count_changes to be my final result
thank you
By default, javascript's comparison of strings is case sensitive, therefore you can check a character's case by comparing it to either an upper or lower case converted value.
If it is the same, then the case is what you checked against, if not, the case is different.
"TRY" == "TrY" would return false, whereas "TRY" == "TRY" would return true;
So, use a variable to indicate the case of the last letter checked, then compare the next letter to the opposite case. If it matches, the case has changed, otherwise it is still the same case.
The isLetter function checks a value to be a single character, and using a regex test ensures that it is a letter - no punctuation or digits etc.
Your loop would always produce an error because you were iterating outside the lenth of the message string - arrays are 0 based.
let message = "heY, WHAt are you dOING?";
let count_changes = 0;
let lowerCase = message[0] == message[0].toLowerCase();
let messageLength = message.length;
function isLetter (val) {
// Check val is a letter of the alphabet a - z ignoring case.
return val.length == 1 && val.match(/[a-z]/i);
}
for (let i = 0; i < messageLength; i++) {
var char = message[i];
if (isLetter(char)) {
if(lowerCase) {
// Check to see if the next letter is upper case when the last one was lower case.
if(char == char.toUpperCase()) {
lowerCase = false;
count_changes++;
}
}
else {
// Check to see if the next letter is lower case when the last one was upper case.
if(char == char.toLowerCase()) {
lowerCase = true;
count_changes++;
}
}
}
else {
// Found a non-letter character.
console.error('Not a letter.');
}
}
console.log("Number of times the case changed: " + count_changes);
TL;DR:
let message = "heY, WHAt are you dOING?";
let newMessage = "";
let count_changes = 0;
let isLowerCaseLetter = (letter) => 'a' <= letter && letter <= 'z';
let isUpperCaseLetter = (letter) => 'A' <= letter && letter <= 'Z';
/* Iterate over every character of the message. */
for (let i = 0; i < message.length; i++) {
/* Cache the character at the current index. */
let character = message[i];
/* Check whether the character is a lowercase letter. */
if (isLowerCaseLetter(character)) {
newMessage += character.toUpperCase();
count_changes++;
}
/* Check whether the character is an uppercase letter. */
else if (isUpperCaseLetter(character)) {
newMessage += character.toLowerCase();
count_changes++;
}
/* Otherwise, just add the current character to the new message. */
else newMessage += character;
}
console.log("New Message: ", newMessage);
console.log("Changes: ", count_changes);
Your Mistakes:
The way you're checking if a character is a letter is wrong, due to >='z'. It should be <='z'. The same goes for the check against 'Z'.
Functions that have a Boolean connotation had better return true or false instead of -1 or the character itself as you do.
Inside isLetter you pass the index instead of the character itself. The function call should be isLetter(message[i]) instead of isLetter(i).
The very message you are testing will be deemed a 'bad string', because of the comma and the spaces between the words.
In your loop, the condition should be i < message.length, otherwise, every message will be deemed a 'bad string', because you'll exceed all characters and get an undefined value.
The methods toLowerCase and toUpperCase do not affect the original string but create a new one instead. If you want to assemble the resulting characters together, you have to initialise a newMessage string and concatenate it the processed character each loop.
Suggested solution:
Instead of one isLetter function create one checking if a character is a lowercase letter and one checking if it's an uppercase letter. That way you combine your checks and your if clause will be much simpler and more readable.
Ditch the isLetter check and the good string / bad string thing completely, so as not to have problems with in-between characters such as spaces and punctuation.
Attempt to minimise function calls, as for large strings, they will slow down your code a lot. In the code below, only 2 function calls per loop are used, compared to the accepted answer, which makes:
3 function calls per loop plus,
3 function calls when a character is letter (the majority of the time)
3 one-time function calls for from, map and join, which will matter for large strings.
Speedtest:
In a series of 5 tests using a massive string (2,825,856 chars long) the answers stack up as follows:
this answer (jsFiddle used):
[1141.91ms, 1150.93ms, 1093.75ms, 1048.50ms, 1183.03ms]
accepted answer (jsFiddle used):
[2211.30ms, 2985.22ms, 2136.73ms, 2279.26ms, 2482.34ms]
From what I understand, you want to count the number of characters in the string and return a string where all uppercase characters are replaced with lowercase characters and all lowercase characters are replaced with uppercase characters. Additionally, you want to increment countChanges once for every character changed.
This code should do what you want:
let message = "heY, WHAt are you dOING?";
let countChanges = 0;
let isLetter = c => c.toLowerCase() !== c.toUpperCase();
let isLowerCase = c => c.toLowerCase() === c;
let flippedMessage = Array.from(message).map((c)=>{
if(!isLetter(c)){
return c;
}
countChanges++;
// return uppercase character if c is a lowercase char
if(isLowerCase(c)){
return c.toUpperCase();
}
// Here, we know c is an uppercase character, so return the lowercase
return c.toLowerCase();
}).join('');
// flippedMessage is "HEy, whaT ARE YOU Doing?"
// countChanges is 18
Related
So a string is entered, and then this is, while very poorly done, meant to check each char in the string and if the char is upper case it is meant to output that back into a new string that is the same as the old one with the word capital written after the letter. What it is doing is for every instance of the capital letter it is concating another capital onto the first instance. Each letter should end up with its own marker, but it is instead being bundled on one.
let str = 'I am In A Big Iron Arboretum.';
let nstr = str;
while (i \<= len) {
let char = str.charAt(i);
if (char == char.toLowerCase()) {
//console.log('oi');
} else {
if (char == char.toUpperCase()) {
let fchar = char + ' capital';
//console.log(fchar);
nstr = nstr.replace(char, fchar);
//console.log(nstr);
}
}
i++;
}
This is what I have tried doing, I at first thought it was just missing some but the console reads it all then I found that the instances after the first letter match the amount of times that letter appears. I am intending for the program to concat the word capital after the letters it finds are capitals. It doesn't matter that the base words are broken up.
I've a variable named var text = 'Saif'
So how can I check the first character of this value (S) is a letter, number or special character??
I've already tried with the code bellow -
var text = 'Saif'
var char = /[A-Z]/g
var num = /[0-9]/g
if (text.match(char)) {
console.log("The string starts with Letter")
} else if (text.match(num)){
console.log("The string starts with Number")
} else {
console.log("The string starts with Special character")
}
It's working fine with the condition of letter and number. But I can't being able to find the special character instead of letter or number.
How can I do that?
First of all, char is a reserved word in JavaScript - best not to use it in your variable names.
Secondly, if you want to test a pattern but not actually retrieve the match, use test() rather than match().
Thirdly, your current patterns don't enforce only the first character of the string; they allow any character within it.
if (/^[a-z]/ig.test(text))
console.log("The string starts with Letter")
else if (/^\d/.test(text))
console.log("The string starts with Number")
else
console.log("The string starts with Special character")
Try this:
var text = 's2Saif'
var char = /^[A-Z]/g
var num = /^\d/g
if (text.match(char)) {
console.log("The string starts with Letter")
} else if (text.match(num)){
console.log("The string starts with Number")
} else {
console.log("The string starts with Special character")
}
Does Letter contain lowercase character? If so, let var char = /^\w/g;
Give this a try:
var format = /[ `!##$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/;
// This ↓ method will return true or false value.
if (format.test(text)) {
console.log("The string starts with Special character");
}
I have created a JS fiddle https://jsfiddle.net/95r110s9/#&togetherjs=Emdw6ORNpc
HTML
<input id="landlordstreetaddress2" class="landlordinputs" onfocusout="validateinputentries()" />
JS
validateinputentries(){
landlordstreetaddress2 = document.getElementById('landlordstreetaddress2').value;
goodcharacters = "/^[a-zA-Z0-9#.,;:'\s]+$/gi";
for (var i = 0; i < landlordstreetaddress2.length; i++){
if (goodcharacters.indexOf(landlordstreetaddress2.charAt(i)) != -1){
console.log('Character is valid');
}
}
}
Its pulling the value from an input and running an indexOf regex expression with A-Z a-z and 0-9 with a few additional characters as well.
The problem is that it works with the entry of BCDEFG...etc and 12345...etc, but when I type "A" or "Z" or "0" or "1", it returns incorrectly.
I need it to return the same with 0123456789, ABCDEF...XYZ and abcdef...xyz
I should point out that the below does work as intended:
var badcharacters = "*|,\":<>[]`\';#?=+/\\";
badcharacter = false;
//firstname
for (var i = 0; i < landlordfirstname.value.length; i++){
if (badcharacters.indexOf(landlordfirstname.value.charAt(i)) != -1){
badcharacter = true;
break;
}
if(landlordfirstname.value.charAt(0) == " "){
badcharacter = true;
break;
}
}
String.prototype.indexOf()
The indexOf() method returns the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex. Returns -1 if the value is not found.
So, you're trying to search this value "/^[a-zA-Z0-9#.,;:'\s]+$/gi" which "never" will be found in the entered string.
You actually want to test that regexp against the entered value.
/^[a-zA-Z0-9#.,;:'\s]+$/gi.test(landlordstreetaddress2)
function validateinputentries() {
var landlordstreetaddress2 = document.getElementById('landlordstreetaddress2').value;
if (/^[a-zA-Z0-9#.,;:'\s]+$/gi.test(landlordstreetaddress2)) {
console.log('Characters are valid');
} else {
console.log('Characters are invalid');
}
}
<input id="landlordstreetaddress2" class="landlordinputs" onfocusout="validateinputentries()" />
You're trying to combine two different methods of testing a string -- one way is with a regex; the other way is by checking each character against a list of allowed characters. What you've wound up with is checking each character against a list of what would have been a regex, if you hadn't declared it as a string.
Those methods conflict with each other; you need to pick one or the other.
Check each character:
This is closest to what you were attempting. You can't use character ranges here (like a-zA-Z) as you would in a regex; you have to spell out each allowed character individually:
var validateinputentries = function() {
var address = document.getElementById('landlordstreetaddress2').value;
var goodcharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#.,;:' ";
var badcharactersfound = false;
for (var i = 0; i < address.length; i++) {
if (goodcharacters.indexOf(address.charAt(i)) == -1) {
badcharactersfound = true;
console.log("not allowed: ", address.charAt(i));
}
}
if (badcharactersfound) {
// Show validation error here
}
}
<input id="landlordstreetaddress2" class="landlordinputs" onfocusout="validateinputentries()" />
Regular Expressions
The regex version is much simpler, because the regular expression is doing most of the work. You don't need to step through the string, just test the whole string against the regex and see what comes out. In this case you're looking to see if the input contains any characters that aren't allowed, so you want to use the character exception rule: [^abc] will match any character that is not a, b, or c. You don't want to anchor the match to the beginning or the end of the string, as you were doing with the initial ^ and the trailing $; and you can leave out the + because you don't care if there are sequential bad characters, you just care if they exist at all.
var validateinputentries = function() {
var address = document.getElementById('landlordstreetaddress2').value;
var regex = new RegExp("[^a-zA-Z0-9#.,;:'\\s]","g")
var badcharactersfound = address.match(regex);
// or the above two lines could also have been written like this:
// var bad = address.match(/[^a-zA-Z0-9#.,;:'\s]/g)
// In either case the "g" operator could be omitted; then it would only return the first bad character.
if (badcharactersfound) {
console.log("Not allowed: ", badcharactersfound);
}
}
<input id="landlordstreetaddress2" class="landlordinputs" onfocusout="validateinputentries()" />
I'm hoping someone can explain to me why I need to use "toLowerCase()" if I'm already using a regular expression that is case insensitive "i".
The exercise is a pangram that can accept numbers and non-ascii characters, but all letters of the alphabet MUST be present in lower case, upper case, or mixed. I wasn't able to solve this exercise correctly until I added "toLowerCase()". This is one of the javascript exercises from exercism.io. Below is my code:
var Pangram = function (sentence) {
this.sentence = sentence;
};
Pangram.prototype.isPangram = function (){
var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi,
x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);
for (var i = 0; i < alphabet.length; i++){
if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
return false;
}
}
return true;
};
module.exports = Pangram;
The regex may not be doing what you think it's doing. Here is your code commented with what's going on:
Pangram.prototype.isPangram = function (){
var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi,
x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);
// for every letter in the alphabet
for (var i = 0; i < alphabet.length; i++){
// check the following conditions:
// letter exists in the sentence (case sensitive)
// AND sentence contains at least one letter between a-z (start to finish, case insensitive)
if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
return false;
}
}
return true;
}
The logic that is checking whether each letter is present has nothing to do with the regex, the two are serving separate purposes. In fact, based on your description of the problem, the regex will cause your solution to fail in some cases. For example, assume we have the string "abcdefghijklmnopqrstuvwxyz-". In that case your regex will test false even though this sentence should return true.
My advice would be to remove the regex, use toLowerCase on the sentence, and iterate through the alphabet checking if the sentence has each letter - which you seems to be the track you were on.
Below is a sample solution with some tests. Happy learning!
function isPangram (str) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const strChars = new Set(str.toLowerCase().split(''))
return alphabet.split('').every(char => strChars.has(char))
}
const tests = [
"abc",
"abcdefghijklmnopqrstuvwxyz",
"abcdefghijklmnopqRstuvwxyz",
"abcdefghijklmnopqRstuvwxyz-",
]
tests.forEach(test => {
console.log(test, isPangram(test))
})
It's because you're manually checking for lowercase letters:
if (x.indexOf(alphabet[i]) === -1)
alphabet[i] will be one of your alphabet string, which you have defined as lowercase.
It looks like you don't need the regex at all here, or at least it's not doing what you think it's doing. Since your regex only allows for alpha characters, it will fail if your sentence has any spaces.
I am trying to write a function that decryptes an encrypted message that has uppercase letters (showing its a new word) and lower case characters (which is the word itself). The function needs to search through the encrypted message for all the uppercase letters and then returns the uppercase character along with lower case that follows it. I have been given a function to call on within the decrypt function:
function isUpperCase(aCharacter)
{
return (aCharacter >= 'A') && (aCharacter <= 'Z');
}
I was thinking that I would search through the word for all the uppercase characters first and assign that as a new string. I could then do while loop that will pick up each of the letters in the new string and then search for the lower case characters that are next to it in the old string.
However, I am completely stuck at the first part - I cant even work out the structured English.
The code is:
encryptMessage is a string containing uppercase and lowercase characters
indexCharacter is used at a later date for another function
upperAlphabet - alphabet of uppercase characters - used later
lowerAlphabet - alphabet lowercase characters - used later
The function:
function decryptMessage(encryptMessage, indexCharacter, upperAlphabet, lowerAlphabet)
{
var letter
var word = "";
for (var count = 0; count < encryptMessage.length; count = count +1);
{
letter = encryptMessage.charAt(count)
if (isUpperCase(letter));
{
word = word + letter;
}
document.write(word); //this is just to test to see if it returns the uppercase - I would use the return word
}
The above just doesnt seem to work, so I cant even continue with the rest of the code. Can anyone help me identify where i have gone wrong - have I completely gone the wrong direction with this anyway, reading it back I dont think it really makes much sense ?? Its a very basic code, I have only learnt, for, while loops - if and else functions really, i am just soooooo stuck.
thanks in advance for your advice :-)
Issy
I'm not too sure I follow, but you can strip using the replace method and regular expressions
var str = 'MaEfSdsfSsdfsAdfssdGsdfEsdf';
var newmsg = str.replace(/[a-z]/g, '');
var old = str.replace(/[A-Z]/g, '');
In this case, newmsg = 'MESSAGE'.
A simple condition for checking uppercase characters in a string would be...
var str = 'aBcDeFgHiJkLmN';
var sL = str.length;
var i = 0;
for (; i < sL; i++) {
if (str.charAt(i) === str.charAt(i).toUpperCase()) {
console.log('uppercase:',str.charAt(i));
}
}
/*
uppercase: B
uppercase: D
uppercase: F
uppercase: H
uppercase: J
uppercase: L
uppercase: N
*/
EDIT
String input = "ThisIsASecretText";
for(int i = 0; i < input.Length; i++)
{
if(isUpperCase(input.charAt(i))
{
String nextWord = String.Empty;
for(int j = i; j < input.Length && !isUpperCase(input.charAt(j)); j++)
{
nextWord += input.charAt(j);
i++;
}
CallSomeFunctionWithTheNextWord(nextWord);
}
}
The following calls would be made:
CallSomeFunctionWithTheNextWord("This");
CallSomeFunctionWithTheNextWord("Is");
CallSomeFunctionWithTheNextWord("A");
CallSomeFunctionWithTheNextWord("Secret");
CallSomeFunctionWithTheNextWord("Text");
You can do the same thing with much less code using regular expressions, but since you said that you are taking a very basic course on programming, this solution might be more appropriate.
Use Unicode property escapes, in particular the "Lu" General Property Category, which matches uppercase. There are categories for numbers, punctuation, currency, and just about any other category of character you might be interested in.
In the example below, the "u" modifier enables Unicode matching.
"HeLlo WoRld".match(/\p{Lu}/gu) // [ 'H', 'L', 'W', 'R' ]
I would rather use Array.reduce as follows:
say, example sample = 'SampleStringAsFollows';
let capWord = [...sample].reduce((caps,char) => (char.match(/[A-Z]/)) ? caps + char : caps,'');
console.log(capWord); //SSAF
capWord will be a string of CAPITAL CHARACTERS and will also tackle the boundary cases where in the string may contain special characters.
Please Use Below code to get first Capital letter of the sentence :
Demo Code
var str = 'i am a Web developer Student';
var sL = str.length;
var i = 0;
for (; i < sL; i++) {
if (str.charAt(i) != " ") {
if (str.charAt(i) === str.charAt(i).toUpperCase()){
console.log(str.charAt(i));
}
}
}