why this 'repeated character" finding function doesn't work properly? - javascript

JavaScript
This is the function which will give the output "true"if there is a repeated character in a string,,
otherwise it will give output "false"
function repeatChar(str) {
for (let char of str.toLowerCase()) {
if (str.indexOf(char) !== str.lastIndexOf(char)) {
return true;
}
}
return false;
}
console.log(repeatChar('aA')); //expected output "true" but here output is "false"... Why??

You're searching for the lowercased character in the original string, which hasn't been converted to all lowercase.
You should replace str with its lowercase version before the loop.
function repeatChar(str) {
str = str.toLowerCase();
for (let char of str) {
if (str.indexOf(char) !== str.lastIndexOf(char)) {
return true;
}
}
return false;
}
console.log(repeatChar('aA')); //expected output "true" but here output is "false"... Why??

Because str.toLowerCase() is ‘aa’ but you’re comparing occurrences in the original string ‘aA’:
// str is still ‘aA’
// str.toLowerCase() returns a *new string* and leaves str unchanged
str.indexOf(char) // “aA”.indexOf(‘a’) === 0
str.lastIndexOf(char) // “aA”.indexOf(‘a’) === 0

When you reference "str.indexOf(char)" in the "if" check you are not referencing the lower case version of str, but rather the original version with upper case.
If you want to reference the lower case version, you can do the following:
function repeatChar(str) {
for (let char of lower_str=str.toLowerCase()) {
if (lower_str.indexOf(char) !== lower_str.lastIndexOf(char)) {
return true;
}
}
return false;
}
console.log(repeatChar('aA'));

str='aA';
str.toLowerCase() is 'aa';
However, unless str is updated i.e. str=str.toLowerCase(), all references to str shall be to its original form i.e. 'aA'.
And, as you rightly know (given you are indeed attempting to use uniform case during comparison), the indexOf() and lastIndexOf() methods are case sensitive

A simpler way to do this would be to construct a Set from the string's characters and compare its size with the original string's length. If they are equal, then there were no repeated characters, as Sets contain only unique values.
function repeatChar(str) {
return new Set([...str.toLowerCase()]).size !== str.length;
}

In this example I split the string into an array then loop over each element of the array. I stored the previous character in the last variable.
function repeatChar(str) {
let last = '';
for (const char of str.toLowerCase().split('')) {
if (char === last) {
return true;
}
last = char;
}
return false;
}
console.log(repeatChar('aA'));

str.toLowerCase() will not change str

Related

javascript program to check if a string is palindromes not returning false

I wrote this bit of code a a part of an exercise to check weather or not a string is palindromes. They program is working correctly in terms of checking the string but it does not return false when the string is not palindromes. What am I doing wrong? thanks
//convert the string to array
var stringArr = [ ];
var bool;
function palindrome(str) {
// make lowercase
var lowerCase = str.toLowerCase();
//remove numbers, special characters, and white spaces
var noNumbers = lowerCase.replace(/[0-9]/g, '');
var noSpecials = noNumbers.replace(/\W+/g, " ");
var finalString = noSpecials.replace(/\s/g, '');
stringArr = finalString.split("");
if (stringArr.sort(frontToBack)==stringArr.sort(backToFront)) {
bool = true;
}
else {
bool= false;
}
return bool;
}
function frontToBack (a,b) {return a-b;}
function backToFront (a,b) {return b-a;}
palindrome("eye");
if (stringArr.sort(frontToBack)==stringArr.sort(backToFront)) { is your problem.
In JavaScript, the sort method updates the value of the variable you are sorting. So in your comparison, once both sort's have run, both end up with the same value (since the second sort, effectively overrides the first).
For example.
var a = [1,7,3];
a.sort();
console.log(a); // will print 1,3,7
Edit: had a quick test, I think eavidan's suggestion is probably the best one.
Edit2: Just put together a quick version of a hopefully working palindrome function :)
function palindrome(str) { return str.split("").reverse().join("") == str;}
It is because string subtraction yields NaN, which means both sorted arrays are the same as the original.
Even if you did convert to ASCII coding, you sort the entire string, then for instance the string abba would be sorted front to back as aabb and back to front as bbaa. (edit: and also what Carl wrote about sort changing the original array. Still - sort is not the way to go here)
What you should do is just reverse the string (using reverse on the array) and compare.
You might do as follows;
var isPalindrome = s => { var t = s.toLowerCase()
.replace(/\s+/g,"");
return [].slice.call(t)
.reverse()
.every((b,i) => b === t[i]);
};
console.log(isPalindrome("Was it a car or a cat I saw"));
console.log(isPalindrome("This is not a palindrome"));
function pal()
{
var x=document.getElementById("a").value;
//input String
var y="";
//blank String
for (i=x.length-1;i>=0;i--)
//string run from backward
{
y=y+x[i];
//store string last to first one by one in blank string
}
if(x==y)
//compare blank and original string equal or not
{
console.log("Palindrome");
}
else
{
console.log("Not Palindrome ");
}
}

Function to extract numbers only from a string

I have written a function that I want to take in a string and then return a string that contains only the number characters from the original string. It
function pureNumbers() {
var result;
for (var i = 0; i < phoneNumber.length; i++) {
if (Number(phoneNumber[i]) !== NaN) {
result ? result = result + phoneNumber[i] : result = phoneNumber[i]
}
}
return result;
}
pureNumbers('(123) 456-7890')
Desired result:
result: '1234567890'
What I actually get is:
result: 'undefined(123) 456-7890'
I know there's two issues here (possibly more).
The undefined at the beginning of my result is because my function is attempting to return the value of result in the first loop's iteration, before anything has been assigned to it. I set up the ternary conditional to cover this, not sure why it's not working...
My first if() conditional is intended to make the given character of the string be added to result only if it is a number, yet every single character is being added.
Any help appreciated - thanks in advance.
This gets all the numbers from a string as an array, then .join("") to join together the strings with no delimiter between them, I.e., a consecutive concatenation string of digit matches.
var numberPattern = /\d+/g;
'something102asdfkj1948948'.match( numberPattern ).join("");
Yields "1021948948"
The basic logic is below:
var x = 'Hello please call (727) 902-1112';
var numbers = x.match(/[0-9]/g).join('');
console.log(numbers);
Result: 7279021112
Now as to a function, I think this might help you:
var x = 'Hello please call';
var y = 'Hello please call (727) 902-1112';
function pureNumbers(param) {
result = param.match(/[0-9]/g);
if (Array.isArray(result)) {
return result.join('');
}
return false;
}
console.log(pureNumbers(x)); // returns false
console.log(pureNumbers(y)); // returns 7279021112
Note: isArray() does not work in older versions of IE 9. You would have to do it differently.
Your can also try the following: string.replace(/[^0-9]/g, ''); OR string.replace(/\D/g,''); to strip all the non-digit characters.
function pureNumbers(str) {
var num = str.replace(/[^0-9]/g, '');
return num;
}
alert(pureNumbers('(123) 456-7890'));
I only changed your function a little bit, though it can be solved in many ways, especially with regex.
function pureNumbers(phoneNumber) {
var result = "";
for (var i = 0; i < phoneNumber.length; i++) {
if (!isNaN(phoneNumber[i]) && phoneNumber[i].trim() !== '') {
result += phoneNumber[i];
}
}
return result;
}
Hope you may get some hint and improve for better solution.

How to check if a string is a palindrome JavaScript [CLOSED!]

I'm trying to make a function that will check if a word is a palindrome. If the word is a palindrome it will return true else it will return false. "You'll need to remove all non-alphanumeric characters (punctuation, spaces and symbols) and turn everything lower case in order to check for palindromes.
We'll pass strings with varying formats, such as "racecar", "RaceCar", and "race CAR" among others."
My code is:
function palindrome(str) {
str = str.toLowerCase().replace(/[^a-z]+/g,"");
if (str === str.split("").reverse().join("")){
return str;
} else {
return "This is not a palindrome";
}
}
Could somebody tell me what is wrong with this code please?
How about this solution.
function palindrome(str) {
str = str.toLowerCase().replace(/[^a-z0-9]+/g,"");
return str === str.split("").reverse().join("");
}
It strips non alpha-numeric characters, turns into lower case, and returns true | false
"alphanumeric" means both alphabetical and numerical characters. Try something like this:
function isPalindrome(str) {
str = str.toLowerCase().replace(/[^a-z0-9]+/g, '');
return str === str.split('').reverse().join('');
}
isPalindrome('racecar')
// => true
isPalindrome('race car')
// => true
isPalindrome('race caR')
// => true
It doesn't work because it always return a "true" because if not palindrome, then return a string, which evaluated as a boolean is true.

Javascript, string, RegEx, if and else if, console.log different output

I want to output a string's vowels in order, so I decided to use RegEx to do it.
However, when I put the expression in different position in (if and else if), the output is different for the same expression. Could anyone explain?
function ordered_vowel_word(str) {
if(str.match(/[aeiou]{1,}/g) !== ""){
var arr = str.match(/[aeiou]{1,}/g);
console.log(arr);
}
else
console.log(str);
}
ordered_vowel_word("bcg");
ordered_vowel_word("eebbscao");
/* The Output */
ordered_vowel_word("bcg");
==> null
ordered_vowel_word("eebbscao");
==> ["ee", "ao"]
But if I restructure the expression,
function ordered_vowel_word(str) {
if(str.match(/[^aeiou]/) !== "")
console.log(str);
else if(str.match(/[aeiou]{1,}/g) !== ""){
var arr = str.match(/[aeiou]{1,}/g);
console.log(arr);
}
}
The output will be
ordered_vowel_word("bcg");
==> bgv
ordered_vowel_word("eebbscao");
==> eebbscao
Take note that string.match returns an array if there is at least one match, and it returns null if there is no match.
What I think you want is :
if(str.match(/[aeiou]{1,}/g) == null){ // no matches
or
if(str.match(/[aeiou]{1,}/g) != null){ //has a match
As for the sorting, you have to do process the array you get with str.match.
Check out this SO answer for sorting arrays. Yes, you can use > and < operators for characters.
The return value of str.match the way you are using it is an array containing the matches when it matches. Also, it is not an empty string when there are no matches... it is actually null.
Try changing what you are testing for in your if condition to this:
str.match(/[aeiou]{1,}/g) !== null)

Javascript IndexOf with integers in string not working

Can anyone tell me why does this not work for integers but works for characters? I really hate reg expressions since they are cryptic but will if I have too. Also I want to include the "-()" as well in the valid characters.
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
Review
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
This String "method" returns true if str is contained within itself, e.g. 'hello world'.indexOf('world') != -1would returntrue`.
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
The value of $('#textbox1').val() is already a string, so the .toString() isn't necessary here.
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
This is where it goes wrong; effectively, this executes '1234'.indexOf('0123456789') != -1; it will almost always return false unless you have a huge number like 10123456789.
What you could have done is test each character in str whether they're contained inside '0123456789', e.g. '0123456789'.indexOf(c) != -1 where c is a character in str. It can be done a lot easier though.
Solution
I know you don't like regular expressions, but they're pretty useful in these cases:
if ($("#textbox1").val().match(/^[0-9()]+$/)) {
alert("valid");
} else {
alert("not valid");
}
Explanation
[0-9()] is a character class, comprising the range 0-9 which is short for 0123456789 and the parentheses ().
[0-9()]+ matches at least one character that matches the above character class.
^[0-9()]+$ matches strings for which ALL characters match the character class; ^ and $ match the beginning and end of the string, respectively.
In the end, the whole expression is padded on both sides with /, which is the regular expression delimiter. It's short for new RegExp('^[0-9()]+$').
Assuming you are looking for a function to validate your input, considering a validChars parameter:
String.prototype.validate = function (validChars) {
var mychar;
for(var i=0; i < this.length; i++) {
if(validChars.indexOf(this[i]) == -1) { // Loop through all characters of your string.
return false; // Return false if the current character is not found in 'validChars' string.
}
}
return true;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.validate(validChars)) {
alert("Only valid characters were found! String validates!");
} else {
alert("Invalid Char found! String doesn't validate.");
}
However, This is quite a load of code for a string validation. I'd recommend looking into regexes, instead. (Jack's got a nice answer up here)
You are passing the entire list of validChars to indexOf(). You need to loop through the characters and check them one-by-one.
Demo
String.prototype.Contains = function (str) {
var mychar;
for(var i=0; i<str.length; i++)
{
mychar = this.substr(i, 1);
if(str.indexOf(mychar) == -1)
{
return false;
}
}
return this.length > 0;
};
To use this on integers, you can convert the integer to a string with String(), like this:
var myint = 33; // define integer
var strTest = String(myint); // convert to string
console.log(strTest.Contains("0123456789")); // validate against chars
I'm only guessing, but it looks like you are trying to check a phone number. One of the simple ways to change your function is to check string value with RegExp.
String.prototype.Contains = function(str) {
var reg = new RegExp("^[" + str +"]+$");
return reg.test(this);
};
But it does not check the sequence of symbols in string.
Checking phone number is more complicated, so RegExp is a good way to do this (even if you do not like it). It can look like:
String.prototype.ContainsPhone = function() {
var reg = new RegExp("^\\([0-9]{3}\\)[0-9]{3}-[0-9]{2}-[0-9]{2}$");
return reg.test(this);
};
This variant will check phones like "(123)456-78-90". It not only checks for a list of characters, but also checks their sequence in string.
Thank you all for your answers! Looks like I'll use regular expressions. I've tried all those solutions but really wanted to be able to pass in a string of validChars but instead I'll pass in a regex..
This works for words, letters, but not integers. I wanted to know why it doesn't work for integers. I wanted to be able to mimic the FilteredTextBoxExtender from the ajax control toolkit in MVC by using a custom Attribute on a textBox

Categories