I need a JavaScript function to tell me whether a string object is empty. By "empty", I mean that it's not all just whitespace characters. I've written this prototype:
String.prototype.isEmpty = function() {
return this.length === 0 || this === " " || this.test(/^\s*$/);
}
Is this alright?
Is there a more-performant version of this out there?
Use
String.prototype.isEmpty = function() {
if (!this.match(/\S/)) {
return ('enter some valid input.Empty space is not allowed');
} else {
return "correct input";
}
}
alert("test 1:"+(" ".isEmpty()));
alert("test 2:"+(" \t ".isEmpty()));
alert("test 3:"+(" \n ".isEmpty()));
alert("test 4:"+("hi".isEmpty()));
Note:
\s will match a whitespace character: space, tab or new line.
\S will match non whitespace character:anything but not a space, tab or new line.
If your string has a single character which is not a space, tab or new line, then it's not empty.
Therefore you just need to search for one character: \S
It looks like you need to use /^\s*$/.test(this) instead of this.test(/^\s*$/). There is no test() method for strings, unless you're using some JavaScript library that implements this method.
The /^\s*$/.test(this) would have been enough, but the first two expressions would short circuit if any one of them evaluates to true, without having to test the regular expression. That should be pretty efficient.
As #Matthew Crumley noted in a comment above, your this === " " expression will always evaluate to false. You could remove this expression, or use == if you would will be expecting a lot of strings with just a single space character:
String.prototype.isEmpty = function() {
return this.length === 0 || this == " " || /^\s*$/.test(this);
}
String.prototype.isEmpty = function() {
return this.length == 0 || /^\s*$/.test(this);
}
There is just a possibility out of 255 (not considering Unicode characters with code greater than 255) that a string with length 1 contains the space character. Considering strings with lenght greater than 1, the possibility get even lower.
Generally, using RegExp.prototype.test for checking for a pattern match without compilation of a return array of matches (String.prototype.match) likely has a better performance. I'd try -- but haven't tested yet -- something like:
function isEmpty() {
var string = arguments[0] ;
var EMPTY_STRING_PATTERN = /^\s*$/ , empty = false ;
if( EMPTY_STRING_PATTERN.exec(string) === true ) empty = true ;
return empty ;
}
On a side note, it is considered bad practice to fiddle with the prototype object of core javascript objects.
from example https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/Trim
var orig=" foo "
document.write(orig.trim()) // foo
document.write(orig.trim().length) // 3
tested on FF 3.6.8, Safari 5.0.1, Google Chrome 5.0.375.127, but produce js error on IE 8
I fiddled with some of the things:
I'm returning the inverse of this.length, for 0 that is true, for everything other number that is false.
I removed the check for " ". I actually haven't seen much, if any cases where a single space was entered, removing the check is IMO faster on average.
And flipped the regex <-> string like the others did.
String.prototype.isEmpty = function() {
return !this.length || /^\s*$/.test(this);
}
Same answer as Daniel Vassallo originally provided, in example form.
String.prototype.isEmpty = function() {
return /^\s*$/.test(this);
}
document.body.style="background-color:black; color:green;font-size:12pt;font-family: 'Courier New', monospace;font-weight: bold";
String.prototype.isEmpty = function() {
return /^\s*$/.test(this);
}
let test0 = ''.isEmpty();
let test1 = '\xa0'.isEmpty();
let test2 = ' '.isEmpty();
let test3 = '\t'.isEmpty();
let test4 = '\n'.isEmpty();
let test5 = '\n\n'.isEmpty();
let test6 = '\n\t\n'.isEmpty();
let test7 = '\r\n'.isEmpty();
let test8 = '\r\t\n'.isEmpty();
let test9 = '\r\n\t'.isEmpty();
var texts = new Array(
("String.prototype.isEmpty = function() {"),
(" return /^\s*$/.test(this);"),
("}"),
(""),
("let test0 = ''.isEmpty() // " + test1),
("let test1 = ' '.isEmpty() // " + test2) + " (non breaking space)",
("let test2 = ' '.isEmpty() // " + test2),
("let test3 = '\\t'.isEmpty() // " + test3),
("let test4 = '\\n'.isEmpty() // " + test4),
("let test5 = '\\n\\n'.isEmpty() // " + test5),
("let test6 = '\\n\\t\\n'.isEmpty() // " + test6),
("let test7 = '\\r\\n'.isEmpty() // " + test7),
("let test8 = '\\r\\t\\n'.isEmpty() // " + test8),
("let test9 = '\\r\\n\\t'.isEmpty() // " + test9)
);
texts.forEach(text => {
let nobreakchar = '\xa0'
;
document.body.append(document.createTextNode(text.replaceAll(" ",nobreakchar)))
document.body.append(document.createElement("br"))
});
Instead of writing more number of lines let's finish it in 2 lines only.
String.prototype.isEmpty = function () {
return this.length === 0 || this.trim() === ""
}
With trim() you don't need to worry about if the variable is only having space characters and that is how you can avoid those falling in regex
Related
hello I would like to know what is the best way to search pattern like
AB where A should be any except A and B should only be B ? Exempple : 'ADSDFSDAB' should return false where as 'BBBSDSSDSDNSSS' should return true.
So, for every B in my string, I want to return true if there is no A preceding it.
where A should be any except A...
So that's [^A]
and B should only be B
And that's B.
So:
if (/[^A]B/.test(str))) {
// Yes, it has a match
} else {
// No, it doesn't
}
Live Example:
test("ADSDFSDAB", false);
test("BBBSDSSDSDNSSS", true);
function test(str, expect) {
var result = /[^A]B/.test(str);
var good = !result == !expect;
console.log("'" + str + "': " + result + (good ? " - Pass" : " - FAIL"));
}
From what I understand, you want to match B not followed by A. You can use a patter like:
[^A]B
however, I'd suggest that you search for the existence of the substring AB in your original string and check the result.
originalString.indexOf('AB') !== -1
This question already has answers here:
Why do regex constructors need to be double escaped?
(5 answers)
Closed 6 years ago.
My objective is to check if the number that has been input into a form via HTML meets the following...
Is a number between 0.01 and 100.0
Is a float number e.g. will always of the format 00.01
My RegEx is - "\d{1,3}\.\d{1,2}" - Which when I check on RegExr appears to be correct... http://regexr.com/3eme3
However my code is returning false... Where am I going wrong?
(I've checked it both as a non parsed float number and as a parsed float number)
function checkAgeGrade(){
var ageGradeValue = document.getElementsByName("AgeGrade")[0].value;
console.log("Age Grade input: " + ageGradeValue);
var correctDigits = new RegExp("\d{1,3}\.\d{1,2}");
console.log("Correct digits: " + correctDigits);
if(!hasValue(ageGradeValue)){
document.submitrunnertime.AgeGrade.value = "-1";
}
console.log("has a value");
if(!isNaN(ageGradeValue)){
console.log("passed isNaN");
var parsedAgeGradeValue = parseFloat(ageGradeValue);
console.log(parsedAgeGradeValue);
if(parsedAgeGradeValue > 0.00 && parsedAgeGradeValue < 100.00){
console.log("range passed, value is: " + parsedAgeGradeValue + ", checking RegEx");
console.log("Parsed number: " + correctDigits.test(parsedAgeGradeValue));
console.log("Not Parsed number: " + correctDigits.test(ageGradeValue));
return correctDigits.test(parsedAgeGradeValue);
}
}
console.log("false function");
return false;
}
The function I am using to check to see if the input has a value or not is...
function hasValue(aValue) {
var whiteSpace = new RegExp("\s+");
if (aValue.length >= 1) {
if (whiteSpace.test(aValue)) {
return false;
} else {
return true;
}
return false;
}
Because you're creating your regular expression as a string (which, in this case, is not necessary), you need to double-escape the \d markers. Otherwise, the backslash will be ignored:
var correctDigits = new RegExp("\\d{1,3}\\.\\d{1,2}");
You can also do this:
var correctDigits = /\d{1,3}\.\d{1,2}/;
When you use native regular expression syntax, you don't have to double-escape like you do when the expression is in a string.
var characterName = document.getElementById("pilotName").value;
var characterID = 0;
var charSecStatus = 0;
var corpName = " ";
var allianceName = " ";
//callback
makeRequest('https://api.eveonline.com/eve/CharacterID.xml.aspx?names=' + characterName, function() {
if (xmlhttp.status == OK_RESPONSE) {
//read character info
characterID = xmlhttp.responseXML.getElementsByTagName("row")[0].getAttribute("characterID");
makeRequest('https://api.eveonline.com/eve/CharacterInfo.xml.aspx?characterID=' + characterID, function() {
if (xmlhttp.status == OK_RESPONSE) {
//read character info
characterID = xmlhttp.responseXML.getElementsByTagName("characterID")[0].innerHTML;
charSecStatus = xmlhttp.responseXML.getElementsByTagName("securityStatus")[0].innerHTML;
corpName = xmlhttp.responseXML.getElementsByTagName("corporation")[0].innerHTML;
allianceName = (xmlhttp.responseXML.getElementsByTagName("alliance")[0] || {
innerHTML: ""
}).innerHTML;
}
});
}
});
(partial code pictured, no bracketspam pls)
I'm trying to check if the "alliance" variable is empty because certain '"corp" are not in "alliances" and it would be critical error on website if it tried to display an empty variable, so is there a way to check if allianceName is empty after retrieving it from the XML tree and setting it to like "No Alliance" if it IS empty?
Thanks
You are declaring true variables here
var corpName = " ";
var allianceName = " "
In JavaScript, the value of a string with whitespace characters is actually truthy. While the above values do look empty, the reality is they're not. Try it out yourself.
Boolean(" ");
=> true
To set these variables empty, you need to declare them without whitespace characters
var corpName = "";
var allianceName = "";
After you have this, there are two ways to check if the variable is empty
if (!corpName || !corpName.length)
Assuming, you did accidentally include the whitespace character, there are several ways to fix this. We can modify these strings in these cases.
Boolean(" ".trim());
=> false
In the above example, the trim() function is used to remove whitespace characters from a string.
You could also search the string for non-whitespace characters
/\S/.test(" ")
=> false
The \S modifier finds all non whitespace characters.
Alternatively, you could also use the replace function
Boolean(" ".replace(/\s/g, ''));
The global flag g finds all references to the previous regular expression.
If you just want to check whether there's any value in a variable, then try this,
if (str) {
//do something
}
or,
//when undefined
if (typeof str == 'undefined'){
//do something
}
If you need to check specifically for an empty string over null, then, try this.
//when defined, but empty
if ((str.length == 0)||(str== ""))
{
//do something
}
You can try something like this:
Note: If you value is null or undefined, !value?true:false should work. Also value.length is also good approach but should be used in case of string. If value is number, value.length will return 0, i.e. true for empty check.
function isEmpty(value) {
switch (typeof(value)) {
case "string": return (value.length === 0);
case "number":
case "boolean": return false;
case "undefined": return true;
case "object": return !value ? true : false; // handling for null.
default: return !value ? true : false
}
}
var a = " ";
console.log(a, "is empty:", isEmpty(a))
console.log(a, "is empty:", isEmpty(a.trim()))
a = 0;
console.log(a, "is empty:", isEmpty(a))
a = undefined;
console.log(a, "is empty:", isEmpty(a))
a = null;
console.log(a, "is empty:", isEmpty(a))
Also, you can change
allianceName = (xmlhttp.responseXML.getElementsByTagName("alliance")[0] || {
innerHTML: "
}).innerHTML;
to
allianceName = xmlhttp.responseXML.getElementsByTagName("alliance")[0].innerHTML || "";
I believe in JavaScript there's a function called isset() which takes one argument and returns true if it is set to a value and false if it is not.
var regex = /[A-Za-z]\d[A-Za-z] ?\d[A-Za-z]\d/;
var match = regex.exec(value);
if (match){
if ( (value.indexOf("-") !== -1 || value.indexOf(" ") !== -1 ) && value.length() == 7 ) {
return true;
} else if ( (value.indexOf("-") == -1 || value.indexOf(" ") == -1 ) && value.length() == 6 ) {
return true;
}
} else {
return false;
}
The regex looks for the pattern A0A 1B1.
true tests:
A0A 1B1
A0A-1B1
A0A1B1
A0A1B1C << problem child
so I added a check for "-" or " " and then a check for length.
Is there a regex, or more efficient method?
User kind, postal code strict, most efficient format:
/^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d$/i
Allows:
h2t-1b8
h2z 1b8
H2Z1B8
Disallows:
Z2T 1B8 (leading Z)
H2T 1O3 (contains O)
Leading Z,W or to contain D, F, I, O, Q or U
Add anchors to your pattern:
var regex = /^[A-Za-z]\d[A-Za-z][ -]?\d[A-Za-z]\d$/;
^ means "start of string" and $ means "end of string". Adding these anchors will prevent the C from slipping in to the match since your pattern will now expect a whole string to consist of 6 (sometimes 7--as a space) characters. This added bonus should now alleviate you of having to subsequently check the string length.
Also, since it appears that you want to allow hyphens, you can slip that into an optional character class that includes the space you were originally using. Be sure to leave the hyphen as either the very first or very last character; otherwise, you will need to escape it (using a leading backslash) to prevent the regex engine from interpreting it as part of a character range (e.g. A-Z).
This one handles us and ca codes.
function postalFilter (postalCode) {
if (! postalCode) {
return null;
}
postalCode = postalCode.toString().trim();
var us = new RegExp("^\\d{5}(-{0,1}\\d{4})?$");
var ca = new RegExp(/([ABCEGHJKLMNPRSTVXY]\d)([ABCEGHJKLMNPRSTVWXYZ]\d){2}/i);
if (us.test(postalCode.toString())) {
return postalCode;
}
if (ca.test(postalCode.toString().replace(/\W+/g, ''))) {
return postalCode;
}
return null;
}
// these 5 return null
console.log(postalFilter('1a1 a1a'));
console.log(postalFilter('F1A AiA'));
console.log(postalFilter('A12345-6789'));
console.log(postalFilter('W1a1a1')); // no "w"
console.log(postalFilter('Z1a1a1')); // ... or "z" allowed in first position!
// these return canada postal less space
console.log(postalFilter('a1a 1a1'));
console.log(postalFilter('H0H 0H0'));
// these return unaltered
console.log(postalFilter('H0H0H0'));
console.log(postalFilter('a1a1a1'));
console.log(postalFilter('12345'));
console.log(postalFilter('12345-6789'));
console.log(postalFilter('123456789'));
// strip spaces
console.log(postalFilter(' 12345 '));
You have a problem with the regex StatsCan has posted the rules for what is a valid Canadian postal code:
The postal code is a six-character code defined and maintained by
Canada Post Corporation (CPC) for the purpose of sorting and
delivering mail. The characters are arranged in the form ‘ANA NAN’,
where ‘A’ represents an alphabetic character and ‘N’ represents a
numeric character (e.g., K1A 0T6). The postal code uses 18 alphabetic
characters and 10 numeric characters. Postal codes do not include the
letters D, F, I, O, Q or U, and the first position also does not make
use of the letters W or Z.
The regex should be if you wanted it strict.
/^[ABCEGHJ-NPRSTVXY][0-9][ABCEGHJ-NPRSTV-Z] [0-9][ABCEGHJ-NPRSTV-Z][0-9]$/
Also \d means number not necessarily 0-9 there may be the one errant browser that treats it as any number in unicode space which would likely cause issues for you downstream.
from: https://trajano.net/2017/05/canadian-postal-code-validation/
This is a function that will do everything for you in one shot. Accepts AAA BBB and AAABBB with or without space.
function go_postal(){
let postal = $("#postal").val();
var regex = /^[A-Za-z]\d[A-Za-z][ -]?\d[A-Za-z]\d$/;
var pr = regex .test(postal);
if(pr === true){
//all good
} else {
// not so much
}
}
function postalFilter (postalCode, type) {
if (!postalCode) {
return null;
}
postalCode = postalCode.toString().trim();
var us = new RegExp("^\\d{5}(-{0,1}\\d{4})?$");
// var ca = new RegExp(/^((?!.*[DFIOQU])[A-VXY][0-9][A-Z])|(?!.*[DFIOQU])[A-VXY][0-9][A-Z]\ ?[0-9][A-Z][0-9]$/i);
var ca = new RegExp(/^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]( )?\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i);
if(type == "us"){
if (us.test(postalCode.toString())) {
console.log(postalCode);
return postalCode;
}
}
if(type == "ca")
{
if (ca.test(postalCode.toString())) {
console.log(postalCode);
return postalCode;
}
}
return null;
}
regex = new RegExp(/^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][-]?\d[ABCEGHJ-NPRSTV-Z]\d$/i);
if(regex.test(value))
return true;
else
return false;
This is a shorter version of the original problem, where value is any text value. Furthermore, there is no need to test for value length.
I wanted to write a regex to count the number of spaces/tabs/newline in a chunk of text. So I naively wrote the following:-
numSpaces : function(text) {
return text.match(/\s/).length;
}
For some unknown reasons it always returns 1. What is the problem with the above statement? I have since solved the problem with the following:-
numSpaces : function(text) {
return (text.split(/\s/).length -1);
}
tl;dr: Generic Pattern Counter
// THIS IS WHAT YOU NEED
const count = (str) => {
const re = /YOUR_PATTERN_HERE/g
return ((str || '').match(re) || []).length
}
For those that arrived here looking for a generic way to count the number of occurrences of a regex pattern in a string, and don't want it to fail if there are zero occurrences, this code is what you need. Here's a demonstration:
/*
* Example
*/
const count = (str) => {
const re = /[a-z]{3}/g
return ((str || '').match(re) || []).length
}
const str1 = 'abc, def, ghi'
const str2 = 'ABC, DEF, GHI'
console.log(`'${str1}' has ${count(str1)} occurrences of pattern '/[a-z]{3}/g'`)
console.log(`'${str2}' has ${count(str2)} occurrences of pattern '/[a-z]{3}/g'`)
Original Answer
The problem with your initial code is that you are missing the global identifier:
>>> 'hi there how are you'.match(/\s/g).length;
4
Without the g part of the regex it will only match the first occurrence and stop there.
Also note that your regex will count successive spaces twice:
>>> 'hi there'.match(/\s/g).length;
2
If that is not desirable, you could do this:
>>> 'hi there'.match(/\s+/g).length;
1
As mentioned in my earlier answer, you can use RegExp.exec() to iterate over all matches and count each occurrence; the advantage is limited to memory only, because on the whole it's about 20% slower than using String.match().
var re = /\s/g,
count = 0;
while (re.exec(text) !== null) {
++count;
}
return count;
(('a a a').match(/b/g) || []).length; // 0
(('a a a').match(/a/g) || []).length; // 3
Based on https://stackoverflow.com/a/48195124/16777 but fixed to actually work in zero-results case.
Here is a similar solution to #Paolo Bergantino's answer, but with modern operators. I'll explain below.
const matchCount = (str, re) => {
return str?.match(re)?.length ?? 0;
};
// usage
let numSpaces = matchCount(undefined, /\s/g);
console.log(numSpaces); // 0
numSpaces = matchCount("foobarbaz", /\s/g);
console.log(numSpaces); // 0
numSpaces = matchCount("foo bar baz", /\s/g);
console.log(numSpaces); // 2
?. is the optional chaining operator. It allows you to chain calls as deep as you want without having to worry about whether there is an undefined/null along the way. Think of str?.match(re) as
if (str !== undefined && str !== null) {
return str.match(re);
} else {
return undefined;
}
This is slightly different from #Paolo Bergantino's. Theirs is written like this: (str || ''). That means if str is falsy, return ''. 0 is falsy. document.all is falsy. In my opinion, if someone were to pass those into this function as a string, it would probably be because of programmer error. Therefore, I'd rather be informed I'm doing something non-sensible than troubleshoot why I keep on getting a length of 0.
?? is the nullish coalescing operator. Think of it as || but more specific. If the left hand side of || evaluates to falsy, it executes the right-hand side. But ?? only executes if the left-hand side is undefined or null.
Keep in mind, the nullish coalescing operator in ?.length ?? 0 will return the same thing as using ?.length || 0. The difference is, if length returns 0, it won't execute the right-hand side... but the result is going to be 0 whether you use || or ??.
Honestly, in this situation I would probably change it to || because more JavaScript developers are familiar with that operator. Maybe someone could enlighten me on benefits of ?? vs || in this situation, if any exist.
Lastly, I changed the signature so the function can be used for any regex.
Oh, and here is a typescript version:
const matchCount = (str: string, re: RegExp) => {
return str?.match(re)?.length ?? 0;
};
('my string'.match(/\s/g) || []).length;
This is certainly something that has a lot of traps. I was working with Paolo Bergantino's answer, and realising that even that has some limitations. I found working with string representations of dates a good place to quickly find some of the main problems. Start with an input string like this:
'12-2-2019 5:1:48.670'
and set up Paolo's function like this:
function count(re, str) {
if (typeof re !== "string") {
return 0;
}
re = (re === '.') ? ('\\' + re) : re;
var cre = new RegExp(re, 'g');
return ((str || '').match(cre) || []).length;
}
I wanted the regular expression to be passed in, so that the function is more reusable, secondly, I wanted the parameter to be a string, so that the client doesn't have to make the regex, but simply match on the string, like a standard string utility class method.
Now, here you can see that I'm dealing with issues with the input. With the following:
if (typeof re !== "string") {
return 0;
}
I am ensuring that the input isn't anything like the literal 0, false, undefined, or null, none of which are strings. Since these literals are not in the input string, there should be no matches, but it should match '0', which is a string.
With the following:
re = (re === '.') ? ('\\' + re) : re;
I am dealing with the fact that the RegExp constructor will (I think, wrongly) interpret the string '.' as the all character matcher \.\
Finally, because I am using the RegExp constructor, I need to give it the global 'g' flag so that it counts all matches, not just the first one, similar to the suggestions in other posts.
I realise that this is an extremely late answer, but it might be helpful to someone stumbling along here. BTW here's the TypeScript version:
function count(re: string, str: string): number {
if (typeof re !== 'string') {
return 0;
}
re = (re === '.') ? ('\\' + re) : re;
const cre = new RegExp(re, 'g');
return ((str || '').match(cre) || []).length;
}
Using modern syntax avoids the need to create a dummy array to count length 0
const countMatches = (exp, str) => str.match(exp)?.length ?? 0;
Must pass exp as RegExp and str as String.
how about like this
function isint(str){
if(str.match(/\d/g).length==str.length){
return true;
}
else {
return false
}
}