How to match multiple strings using regular expression? - javascript

I have a bunch of strings to match for Bonfire: Palindrome in FreeCodeCamp
The strings are:
eye
racecar
not a palindrome
A man, a plan, a canal. Panama
nope
almostomla
My age is 0, 0 si ega ym.
1 eye for of 1 eye.
0_0 (: /-\ :) 0-0
My Code:
function palindrome(str) {
var newstr = str.replace(/[^\w_-]/g,"").toLowerCase();
var num = newstr.length;
for(var i=0;i<=Math.floor(num/2);i++)
{
if(newstr[i]!==newstr[num-i])
{
return newstr;
}
}
return true;
}
What could be wrong in the if statement? the return of the string is alright.. Just can't wrap my head around these Regular expressions?
My current regular expression:
var newstr = str.replace(/[^\w_-]/g,"").toLowerCase();
matches almost all the strings but the last one. Where am I going wrong?

The last one is not a palindrome; you have 0_0 at the beginning, 0-0 at the end, and do not erase those characters.
As a pedantic note, this is not, strictly speaking, a regular language.

Indexes in an array or string run from 0 to length-1. But when you access the elements at the end of the string, you're going from num, not num-1. You need to subtract an additional 1 when you subtract from the end. So it should be:
if (newstr[i] != newstr[num-i-1]) {
return newstr;
}

So while the answers were useful, they did not provide a correct regular expression. Shoot out to #Barmar for pointing at the right direction. This is my regular expression.
var newstr = str.replace(/[\W_]/g,'').toLowerCase();
The full code for Palindrome in FCC:
function palindrome(str) {
var newstr = str.replace(/[\W_]/g,'').toLowerCase();
var num = newstr.length;
for(var i=0;i<=Math.floor(num/2);i++)
{
if(newstr[i]!==newstr[num-1-i])
{
return false;
}
}
return true;
}
palindrome("0_0 (: /-\ :) 0-0");

Related

Algorithm - Search and Replace a string

I am doing a algorithm in freeCodeCamp.(https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/search-and-replace)
The task is as below:
Perform a search and replace on the sentence using the arguments provided and return the new sentence.
First argument is the sentence to perform the search and replace on.
Second argument is the word that you will be replacing (before).
Third argument is what you will be replacing the second argument with (after).
Note:
Preserve the case of the first character in the original word when you are replacing it. For example if you mean to replace the word "Book" with the word "dog", it should be replaced as "Dog"
**
myReplace("Let us get back to more Coding", "Coding", "algorithms") should return "Let us get back to more Algorithms".
myReplace("Let us go to the store", "store", "mall") should return "Let us go to the mall".
**
//if the before is uppercase, the after should be uppercase also
// str = str.replace(before, after);
var regex = /[A-Z]+/g; //check for uppercase
var newStr = "";
console.log(regex.test(before));
if (regex.test(before)) {
//if uppercase, return true, "after" convert to uppercase
after = after.toUpperCase();
newStr = after[0];
for (var i = 1; i < after.length; i++) {
//start at index=1 letter, all convert to
newStr += after[i].toLowerCase();
}
console.log(newStr);
str = str.replace(before, newStr);
} else {
str = str.replace(before, after);
}
// console.log(newStr);
console.log(str);
return str;
}
I think there should be OK for the code, but can anyone help find why the if statement can't work.
Much thanks!
The problem is that you're calling regex.test() multiple times on the same regular expression instance.
[...]
var regex = /[A-Z]+/g; //check for uppercase
var newStr = "";
console.log(regex.test(before));
if (regex.test(before)) {
//if uppercase, return true, "after" convert to uppercase
after = after.toUpperCase();
[...]
If your string is Hello_there, the first regex.test() will return true, because Hello matched. If you call regex.test() again with the same regex instance, it will have advanced in the string, and try to match starting with _there. In this case, it will fail, because _there does not begin with a capital letter between A and Z.
There are a lot of ways to fix this issue. Perhaps the simplest is to store the result of the first call to a variable, and use it everywhere you're calling regex.test():
[...]
var regex = /[A-Z]+/g; //check for uppercase
var newStr = "";
var upper_check = regex.test(before);
console.log(upper_check);
if (upper_check) {
[...]
It seems overkill to use a regex, when you really need to only check the first character. Your regex will find uppercase letters anywhere...
If the assignment is to only change one occurrence, then a regex is not really the right tool here: it does not really help to improve the code nor the efficiency. Just do:
function myReplace(str, before, after) {
if (before[0] === before[0].toUpperCase()) {
after = after[0].toUpperCase() + after.slice(1);
} else {
after = after[0].toLowerCase() + after.slice(1);
}
return str.replace(before, after);
}
function myReplace(str, before, after) {
var upperRegExp = /[A-Z]/g
var lowerRegExp = /[a-z]/g
var afterCapitalCase = after.replace(/^./, after[0].toUpperCase());
if (before[0].match(upperRegExp)) {
return str.replace(before, afterCapitalCase)
} else if (after[0].match(upperRegExp) && before[0].match(lowerRegExp)) {
return str.replace(before, after.toLowerCase());
} else {
return str.replace(before, after)
}
}

palindrome regex

function palindrome(str) {
// Good luck!
var a = str.replace(/\s|[0-9_]|\W|[#$%^&*()]/g, "").toLowerCase();
if (a === a.split("").reverse().join("")) {
return true;
}
return false;
}
palindrome("eye");
palindrome("1 eye for of 1 eye.") //should return false.
I have done this task on freecodecampus.com. Can anyone tell me why it should give false? If we are removing dot and punctuations, then isn't it right that it should return true?
According to your comment "Note You'll need to remove all non-alphanumeric characters (punctuation, spaces and symbols)", you have to keep alphanumeric characters (ie. letters AND digits). So remove NON alphanum characters (ie. [\W_]). \W is the negation of \w: [^a-zA-Z0-9_]
This is done with:
var test = [
"racecar",
"RaceCar",
"race CAR",
"2A3*3a2",
"2A3 3a2",
"2_A3*3#A2",
"1 eye for of 1 eye."
];
function palindrome(str) {
var a = str.replace(/[\W_]+/g, "").toLowerCase();
if (a === a.split("").reverse().join("")) {
return true;
}
return false;
}
console.log(test.map(function (a) {
return a+' : '+palindrome(a);
}));
function palindrome(str) {
// Good luck!
var a = str.replace(/\s|[0-9_]|\W|[#$%^&*()]/g, "").toLowerCase();
// Here print a
// a = "eyeforofeye"; which is perfect palindrome
if (a === a.split("").reverse().join("")) {
// will pass this condition
return true;
}
return false;
}
palindrome("1 eye for of 1 eye.")
See my comments in the code. The replace method is using a regex to replace all numbers, special character and spaces with nothing. So all you get is a single word with no spaces, numbers and special characters.
In your case you will get eyeforofeye which is perfect palindrome.
You are doing a Rube Goldberg process by providing an overly complicated Regular Expression which could be shorten to /[^a-z]/ and it doesn't return false if you execute your code.
function palindrome(str) {
var a = str.replace(/[^a-z]/ig, '').toLowerCase();
return a === a.split('').reverse().join('');
}
console.log(palindrome('race CAR'));
console.log(palindrome('2A3 3a2'));
console.log(palindrome('eye'));
console.log(palindrome('1 eye for of 1 eye.'));
console.log(palindrome('stack'));
Thanks a lot folks, have done it; Also got some good information on RegeXes. Reading RegEx from Eloquent Javascript, can anyone suggest another better source? Thanx ahead
By the Way As an Answer it took this, ( for those who are interested in answer that passes all ticks in project) ,
function palindrome(str) {
// Good luck!
var a = str.replace(/[^a-z0-9]/ig, "").toLowerCase();
if (a === a.split("").reverse().join("")) {
return true;
}
return false;
}
palindrome("eye");

How do I fix this palindrome checker?

I have tried to make this palindrome checker but it sometimes returns the right answer and sometimes not. Please tell me the bugs in this code... I know that there are more efficient ways to make a palindrome checker but for learning purposes I want to know what is wrong with mine...
function palindrome(str) {
var newString;
//convert string to lower-case
var strLowerCase = str.toLowerCase();
//Find string length
var strLength = str.length;
//replace first 1/2 with second 1/2
newString = replaceLetters(strLowerCase,strLength);
if(newString === strLowerCase){
return true;
}else{
return false;
}
}
function replaceLetters(string,length){
var x;
for(var a = 0; a<Math.ceil(length/2) ; a++){
x = string.replace(string.charAt(a),string.charAt(length-1));
length--;
}
return x;
}
palindrome("eye");
You shouldn't pass the str length as a parameter. Just make a variable length from str.length - 1 in replaceLetters. Also you want math.floor not math.ceil. let's say for a 9 letter words, you only want to swap the first 4 chars not the first 5. You don't need to swap the middle char which is the 5th.Ex: Racecar, you don't swap e with anything to check if its palindrome. You can also use the splice function instead of making your own replace letters function. Some other knitpicking, what's the point of making the strlowercase var since your only calling to lowercase() once?

Palindrome Checker in JavaScript - don't know how to debug

I want to build a palindrome checker in javascript. All non-letter characters should be removed, so that a phrase like "A man, a plan, a canal. Panama" can also be a palindrome.
function reverse(str) {
return str.split("").reverse().join("");
}
function palindrome(str) {
str = str.replace(/[^a-zA-Z]+/,"").toLowerCase();
if(str == reverse(str)) {
return true;
}
else {
return false;
}
}
Now, where is the mistake in the above lines?
The code works on some examples. But for instance "A man, a plan, a canal. Panama" and "never odd or even" return false, meaning somewhere has to be a mistake.
You need to provide the global match flag to your regex:
/[^a-zA-Z]+/g
^
This is a common misconception. The replace() method does not replace all instances of what you want to replace in a string. It simply replaces the first instance and stops. If you refactor your regEx like this:
function reverse(str) {
return str.split("").reverse().join("");
}
function palindrome(str) {
var find = "[^a-zA-Z]";
var regEx = new RegExp(find, 'g');
str = str.replace(regEx,"").toLowerCase();
if(str == reverse(str)) {
return true;
}
else {
return false;
}
}
That will work.
From the example given, it seems to me that the code doesn't work for spaces in between the letters. (There may be other scenarios as well)
I have changed this line :
str = str.replace(/[^a-zA-Z]+/,"").toLowerCase();
To this :
str = str.toLowerCase().replace(/[^a-z]/g,"");
change this line:
str = str.replace(/[^a-zA-Z]+/,"").toLowerCase();
to this:
str = str.toLowerCase().replace(/[^a-z0123456789]+/g,"");
This regex should work for your code.
/[^1-9a-zA-Z]+/g

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