There are many ways to check string valid or not using regex expression and using match/test match accordingly.
I am looking to check whether the expression containing alphabets(a-b), operators (+,-,/,*), only special characters like (')','(') and numerics (0-9) is valid or not
I have already tried for traditional methods pushing when the character is '(' and popping when ')' and checking the balanced parenthesis or not.
Code almost works for even operators but there are some cases where I am lacking behind.
The code provided might be right to some extent.
checkBalancedString(text){
let format = /[A-Za-z0-9]/;
let expression = /[+-\/*]/
if(text.length <=2){
if(format.test(text[0])){
return true;
}
return false;
}
for(let i=0;i<text.length;i++){
let stringcheck=[]
if(text[i]== '('){
stringcheck.push(text[i])
}
switch(text[i]){
case ')':
if(!stringcheck.length){
return false;
}
stringcheck.pop();
break;
}
let checkalphaformat = format.test(text[i]);
if(checkalphaformat){
let nextChar = format.test(text[i+1]);
let nexttonextChar = expression.test(text[i+2])
if(nextChar || nexttonextChar){
return false
}
}else{
let nextChar = format.test(text[i+1]);
if(!nextChar){
return false;
}
if(text[i+2]){
let nextChar = format.test(text[i+2])
if(!nextChar){
return false;
}
}
}
if(!stringcheck.length){
return true;
}
}
}
In short string should return valid where expression like:
(a+b), a+b, a/9, b*5 , (e-6*(d+e)), (a+b)/(c-d)
and expression like:
+, - ,-a,+a-, (a+, (a+v, e*)
The expression should be complete when every character is followed by the operator or parenthesis
either operator is followed by only characters
and parenthesis is followed by the only character.
There should be no operator together from the present index (front and behind)and no two characters together
It looks like what you really want is to check the validity of the formula more than to check a specific kind of formula.
Here's what I use in such a case:
// Return true if the passed string is a valid mathematical expression
// taking as parameter a, b, c, etc.
// Examples:
// 2*a+b*b
// (e-6*(d+e))
// sin(a*PI + b.length) / ( round(d) - log(c) + +("Basse Qualité"===e) )
// for (var i=0, total=0; i<10; i++) total += pow(a,i); return total
check = function(str){
try {
str = str.replace(/(^|[^\."'a-zA-Z])([a-zA-Z]\w+)\b/g, function(s, p, t){
return t in Math ? p + "Math." + t : s;
});
if (!/\breturn\b/.test(str)) str = "return ("+str+")";
var args = "abcdefghijklmnopqrstuvwxyz".split("");
var f = Function.apply(Function, args.concat(str));
f.apply(null, args); // if it works for args it should be ok for numbers...
return true;
} catch (e) {
console.log("error while checking formula", e, str);
return false;
}
}
The basic ideas which should apply to your cases:
try to instantiate a Function with your formula as body and ["a", "b", ...] as argument names
execute this function with a sample input (in my case ["a", "b", ...])
If you don't want such liberty as in my example, you may also test the character ranges (you don't have to allow ; or ̀, if you don't want inline javascript)
Related
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 am trying to validate a string where the first character must be an 'x' and the remaining characters must be numerical. For example:
x1234 == true;
k1234 == false;
x12k4 == false;
1x123 == false;
Here is my code:
function isValidCode(code){
var firstLetter = code.substring(0,1);
var remainingCode = code.substring(1);
var validCode = false;
// Debugging
console.log(firstLetter);
console.log(remainingCode);
if(firstLetter == 'x'){
validCode = true;
}
if(isNumeric(Number(remainingCode))){
validCode = true;
}
}
I've debugged my isNumeric() function, so I'm 99.9% sure the issue isn't there, but here it is just in case:
function isNumeric(numberIn)
{
var returnValue = true;
if (isNaN(numberIn) || isNaN(parseInt(numberIn, 10)))
{
returnValue = false;
}
return returnValue;
}
I've tried several things such as reversing my logic where I start with the given condidtion being true and then checking if(!(firstLetter == 'x')) I've tried == and ===and I've tried casting the remaining portion of the code with Number() , +() and not casting it at all, but none of these seeem to do the trick. The console does log the proper first character and remaining characters in the code so I'm not sure what is wrong.
You can use a regular expression test:
function isValidCode(code) {
return /^[a-z]\d+$/.test(code);
}
I am making an assumption that a lower case letter is required, followed by at least one digit.
To match only only the letter 'x', use:
function isValidCode(code) {
return /^x\d+$/.test(code);
}
You can use RegExp /^x(?=\d+$)/ to match x at beginning of input followed by digits followed by end of input
var arr = ["x1234"
, "k1234"
, "x12k4"
, "1x123"];
var re = /^x(?=\d+$)/;
arr.forEach(function(str) {
console.log(`${str}: ${re.test(str)}`)
})
I have an infix expression: ((attribute1*attribute2)/attribute3+attribute4)
It may vary according to the user input. I want to check whether the expression is valid.
Valid example: ((attribute1*attribute2)/attribute3+attribute4)
Invalid example: (attrribute1*attribute2+*(attribute3)
The second one has no closing parenthesis; also the * operator is not needed. How can I perform this sort of validation in javascript?
Now this is my regex:
/ *\+? *\-? *[a-zA-Z0-9]+ *( *[\+\-\*\/\=\<\>\!\&\|\%] *\+? *\-? *[a-zA-Z0-9]+ *)*/
I need a regex for comparison operators like <= , >= , != , == etc. How can I implement this?
You could try something like this:
function validateInfix(infix) {
var balance = 0;
// remove white spaces to simplify regex
infix = infix.replace(/\s/g, '');
// if it has empty parenthesis then is not valid
if (/\(\)/.test(infix)) {
return false;
}
// valid values: integers and identifiers
var value = '(\\d+|[a-zA-Z_]\\w*)';
// the unary '+' and '-'
var unaryOper = '[\\+\\-]?';
// the arithmetic operators
var arithOper = '[\\+\\-\\*\\/]';
// the comparison operators
var compOper = '(\\<\\=?|\\>\\=?|\\=\\=|\\!\\=)';
// if it has more than one comparison operator then is not valid
if (infix.match(new RegExp(compOper, 'g')).length > 1) {
return false;
}
// the combined final regex: /[\+\-]?(\d+|[a-zA-Z_]\w*)(([\+\-\*\/]|(\<\=?|\>\=?|\=\=|\!\=))[\+\-]?(\d+|[a-zA-Z_]\w*))*/
var regex = new RegExp(unaryOper + value + '((' + arithOper + '|' + compOper + ')' + unaryOper + value + ')*');
// validate parenthesis balance
for (var i = 0; i < infix.length; i++) {
if (infix[i] == '(') {
balance++;
}
else if (infix[i] == ')') {
balance--;
}
if (balance < 0) {
return false;
}
}
if (balance > 0) {
return false;
}
// remove all the parenthesis
infix = infix.replace(/[\(\)]/g, '');
return regex.test(infix);
}
The idea is to check first the parenthesis balance, then remove them all given that we only want to validate and not evaluate, and then match the remaining expression to a regex (which may not be perfect, I'm not a regex expert). And... just in case: infix argument must be a string.
Edit
I noticed a couple of details and changed the code a bit:
Added the operators you needed the regex to match too.
Removed white spaces to get rid of regex junk.
Checked if the expression had empty parenthesis.
Checked if the expression had more than one comparison operators.
Changed this \+?\-? by this [\+\-]?.
Changed string match method by regex test method where possible.
Changed this [a-zA-Z0-9] by this (\d+|[a-zA-Z_]\w*) since the first one matches wrong identifiers like 53abc.
For better understanding and clarity, extracted pieces of regex into separate variables and built the final one from these.
Hope this is ok for you now :)
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
I am using an AJAX-based lookup for names that a user searches in a text box.
I am making the assumption that all names in the database will be transliterated to European alphabets (i.e. no Cyrillic, Japanese, Chinese). However, the names will still contain accented characters, such as ç, ê and even č and ć.
A simple search like "Micic" will not match "Mičić" though - and the user expectation is that it will.
The AJAX lookup uses regular expressions to determine a match. I have modified the regular expression comparison using this function in an attempt to match more accented characters. However, it's a little clumsy since it doesn't take into account all characters.
function makeComp (input)
{
input = input.toLowerCase ();
var output = '';
for (var i = 0; i < input.length; i ++)
{
if (input.charAt (i) == 'a')
output = output + '[aàáâãäåæ]'
else if (input.charAt (i) == 'c')
output = output + '[cç]';
else if (input.charAt (i) == 'e')
output = output + '[eèéêëæ]';
else if (input.charAt (i) == 'i')
output = output + '[iìíîï]';
else if (input.charAt (i) == 'n')
output = output + '[nñ]';
else if (input.charAt (i) == 'o')
output = output + '[oòóôõöø]';
else if (input.charAt (i) == 's')
output = output + '[sß]';
else if (input.charAt (i) == 'u')
output = output + '[uùúûü]';
else if (input.charAt (i) == 'y')
output = output + '[yÿ]'
else
output = output + input.charAt (i);
}
return output;
}
Apart from a substitution function like this, is there a better way? Perhaps to "deaccent" the string being compared?
There is a way to “"deaccent" the string being compared” without the use of a substitution function that lists all the accents you want to remove…
Here is the easiest solution I can think about to remove accents (and other diacritics) from a string.
See it in action:
var string = "Ça été Mičić. ÀÉÏÓÛ";
console.log(string);
var string_norm = string.normalize('NFD').replace(/\p{Diacritic}/gu, ""); // Old method: .replace(/[\u0300-\u036f]/g, "");
console.log(string_norm);
.normalize(…) decomposes the letters and diacritics.
.replace(…) removes all the diacritics.
Came upon this old thread and thought I'd try my hand at doing a fast function. I'm relying on the ordering of pipe-separated ORs setting variables when they match in the function replace() is calling. My goal was to use the standard regex-implementation javascript's replace() function uses as much as possible, so that the heavy-processing can take place in low-level browser-optimized space, instead of in expensive javascript char-by-char comparisons.
It's not scientific at all, but my old Huawei IDEOS android phone is sluggish when I plug the other functions in this thread in to my autocomplete, while this function zips along:
function accentFold(inStr) {
return inStr.replace(
/([àáâãäå])|([çčć])|([èéêë])|([ìíîï])|([ñ])|([òóôõöø])|([ß])|([ùúûü])|([ÿ])|([æ])/g,
function (str, a, c, e, i, n, o, s, u, y, ae) {
if (a) return 'a';
if (c) return 'c';
if (e) return 'e';
if (i) return 'i';
if (n) return 'n';
if (o) return 'o';
if (s) return 's';
if (u) return 'u';
if (y) return 'y';
if (ae) return 'ae';
}
);
}
If you're a jQuery dev, here's a handy example of using this function; you could use :icontains the same way you'd use :contains in a selector:
jQuery.expr[':'].icontains = function (obj, index, meta, stack) {
return accentFold(
(obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase()
)
.indexOf(accentFold(meta[3].toLowerCase())
) >= 0;
};
I searched and upvoted herostwist answer but kept searching and truly, here is a modern solution, core to JavaScript (string.localeCompare function)
var a = 'réservé'; // with accents, lowercase
var b = 'RESERVE'; // no accents, uppercase
console.log(a.localeCompare(b));
// expected output: 1
console.log(a.localeCompare(b, 'en', {sensitivity: 'base'}));
// expected output: 0
NOTE, however, that full support is still missing for some mobile browser !!!
Until then, keep watching out for full support across ALL platforms and env.
Is that all ?
No, we can go further right now and use string.toLocaleLowerCase function.
var dotted = 'İstanbul';
console.log('EN-US: ' + dotted.toLocaleLowerCase('en-US'));
// expected output: "istanbul"
console.log('TR: ' + dotted.toLocaleLowerCase('tr'));
// expected output: "istanbul"
Thank You !
There is no easier way to "deaccent" that I can think of, but your substitution could be streamlined a little more:
var makeComp = (function(){
var accents = {
a: 'àáâãäåæ',
c: 'ç',
e: 'èéêëæ',
i: 'ìíîï',
n: 'ñ',
o: 'òóôõöø',
s: 'ß',
u: 'ùúûü',
y: 'ÿ'
},
chars = /[aceinosuy]/g;
return function makeComp(input) {
return input.replace(chars, function(c){
return '[' + c + accents[c] + ']';
});
};
}());
I think this is the neatest solution
var nIC = new Intl.Collator(undefined , {sensitivity: 'base'})
var cmp = nIC.compare.bind(nIC)
It will return 0 if the two strings are the same, ignoring accents.
Alternatively you try localecompare
'être'.localeCompare('etre',undefined,{sensitivity: 'base'})
I made a Prototype Version of this:
String.prototype.strip = function() {
var translate_re = /[öäüÖÄÜß ]/g;
var translate = {
"ä":"a", "ö":"o", "ü":"u",
"Ä":"A", "Ö":"O", "Ü":"U",
" ":"_", "ß":"ss" // probably more to come
};
return (this.replace(translate_re, function(match){
return translate[match];})
);
};
Use like:
var teststring = 'ä ö ü Ä Ö Ü ß';
teststring.strip();
This will will change the String to a_o_u_A_O_U_ss
You can also use http://fusejs.io, which describes itself as "Lightweight fuzzy-search library.
Zero dependencies", for fuzzy searching.
First, I'd recommend a switch statement instead of a long string of if-else if ...
Then, I am not sure why you don't like your current solution. It certainly is the cleanest one. What do you mean by not taking into account "all characters"?
There is no standard method in JavaScript to map accented letters to ASCII letters outside of using a third-party library, so the one you wrote is as good as any.
Also, "ß" I believe maps to "ss", not a single "s". And beware of "i" with and without dot in Turkish -- I believe they refer to different letters.