How to detect string which contains only spaces? - javascript

A string length which contains one space is always equal to 1:
alert('My str length: ' + str.length);
The space is a character, so:
str = " ";
alert('My str length:' + str.length); // My str length: 3
How can I make a distinction between an empty string and a string which contains only spaces? How can I detect a string which contain only spaces?

To achieve this you can use a Regular Expression to remove all the whitespace in the string. If the length of the resulting string is 0, then you can be sure the original only contained whitespace. Try this:
var str = " ";
if (!str.replace(/\s/g, '').length) {
console.log('string only contains whitespace (ie. spaces, tabs or line breaks)');
}

The fastest solution would be using the regex prototype function test() and looking for any character that is not a space, tab, or line break \S :
if (!/\S/.test(str)) {
// Didn't find something other than a space which means it's empty
}
In case you have a super long string, it can make a significant difference as it will stop processing as soon as it finds a non-space character.

Similar to Rory's answer, with ECMA 5 you can now just call str.trim().length instead of using a regular expression. If the resulting value is 0 you know you have a string that contains only spaces.
if (!str.trim().length) {
console.log('str is empty!');
}
You can read more about trim here.
Edit: After looking at this a few years later I noticed this could be simplified further. Since the result of trim will either be truthy or falsy you can also do the following:
if (!str.trim()) {
console.log('str is empty!');
}

if(!str.trim()){
console.log('string is empty or only contains spaces');
}
String#trim() removes the whitespace at the start and end of the string. If the string contained only whitespace, it would be empty after trimming, and the empty string is falsey in JavaScript.
If the string might be null or undefined, we need to first check if the string itself is falsey before trimming.
if(!str || !str.trim()){
//str is null, undefined, or contains only spaces
}
This can be simplified using the optional chaining operator.
if(!str?.trim()){
//str is null, undefined, or contains only spaces
}

You can Trim your String value by creating a trim function for your Strings.
String.prototype.trim = function () {
return this.replace(/^\s*/, "").replace(/\s*$/, "");
}
now it will be available for your every String and you can use it as
str.trim().length// Result will be 0
You can also use this method to remove the white spaces at the start and end of the String i.e
" hello ".trim(); // Result will be "hello"

You can do this by simply using trim.
var str = " ";
if (str.trim().length == 0)
{
console.log("Your string contains only white spaces.")
}

Trim your String value by creating a trim function
var text = " ";
if($.trim(text.length == 0){
console.log("Text is empty");
}
else
{
console.log("Text is not empty");
}

If we want to check if string contains only white spaces, then this might be helpful.
const str = ' ';
console.log(/^\s+$/.test(str));
This will log true.

Typecasting to Number can detect whitespace-only strings (if strings containing only zeros can be excluded):
if (+' ' === 0) console.log('is whitespace');
to make this approach also work for empty- and zerostrings like '0' a truthy numerical prefix could be used:
if (Number('1 0') === 1) console.log('is not whitespace');
if (Number('1 ' + ' \n ') === 1) console.log('is whitespace');
but concatenated casting is expensive - leading to this obscure expression:
String(x || '').indexOf('0') < +x
however, performance- and readability wise - trimed-length still wins over regex or casting-magic.
const tests = ['',' ', '\t\n\r','0',' 0 ','x',' 404 '];
tests.filter(x => String(x || '').trim().length === 0); // fastest
tests.filter(x => /^\s*$/.test(x)); // 33% slower
tests.filter(x => +x === 0 && String(x).indexOf('0') === -1); // 40 % slower
tests.filter(x => String(x || '').indexOf('0') < +x); // 50% slower
tests.filter(x => Number('1 ' + x) === 1); // 66% slower

This works in Dart not Javascript. However, when I searched up how to do this with Dart this question came up, so I figured others may need the Dart answer.
String foo = ' ';
if (foo.replaceAll(' ', '').length == 0) {
print('ALL WHITE SPACE');
}
else {
print('NOT ALL WHITE SPACE');
}
To further clarify, the String ' d ' will print 'NOT ALL WHITE SPACE' and the String ' ' will print 'ALL WHITE SPACE'.

Related

The difference between "" vs " " Javascript

I used this to remove white spaces from a string.
returnString.split(" ").filter(substr => substr !== "");
In my head it should be this:
returnString.split(" ").filter(substr => substr !== " ") //note the space between the " "
why doesnt the bottom one work? Is it JS sytax?
Answer: If theres a space at the beginning of the string, its split with an empty string, (so substr !== "") removes that from the returned array when splitting the string.
returnString.replace(/\s/g,'') Would be a superior way of doing this.
"" is an empty string.
" " is a space character.
They cannot be used interchangeably.
"" is an empty string.
If there is a space at the beginning of the string, it will split that space with an empty string.
that is why substr !== "" is needed to remove the empty string.
As mentioned in the comments, you’re splitting on whitespaces, creating indices for said whitespaces in an array.
const returnString = 'Hello I am Victor'
const str = returnString.split("").filter(substr => substr !== " ");
console.log(str.join(''))
would get you the desired result.
However, a regex pattern would be best suited for this use case.
returnString.replace(/\s/g, '')

Regex to find 5 consecutive letters of alphabet (ex. abcde, noprst)

I have strings containing 5 letters of alphabet. I would like to match those that contain letters that are consecutive in alphabet for example:
abcde - return match
nopqrs - return match
cdefg - return match
fghij - return match
but
abcef - do not return match
abbcd - do not return match
I could write all combinations but as you can write in Regex [A-Z] I assumed there must be a better way.
A very simple alternative would be to just use String.prototype.includes:
function isConsecutive(string) {
const result = 'abcdefghijklmnopqrstuvwxyz'.includes(string);
console.log(string, result);
}
// true
isConsecutive('abcde');
isConsecutive('nopqrs');
isConsecutive('cdefg');
isConsecutive('fghij');
// false
isConsecutive('abcef');
isConsecutive('abbcd');
If you can live with Python, this function converts the string sequence into numbered characters, and checks if they are consequtive (if so, they are also consecutive alphabetically):
def are_letters_consequtive(text):
nums = [ord(letter) for letter in text]
if sorted(nums) == list(range(min(nums), max(nums)+1)):
return "match"
return "no match"
print(are_letters_consequtive('abcde'))
print(are_letters_consequtive('cdefg'))
print(are_letters_consequtive('fghij'))
print(are_letters_consequtive('abcef'))
print(are_letters_consequtive('abbcd'))
print(are_letters_consequtive('noprst'))
Outputs:
match
match
match
no match
no match
no match
An alternative using javascript:
let string1 = 'abcde'
let string2 = 'fghiz'
function conletters(string) {
if(string.length > 5 || typeof string != 'string') throw '[ERROR] not string or string greater than 5'
for(let i = 0; i < string.length - 1; i++) {
if(!(string.charCodeAt(i) + 1 == string.charCodeAt(i + 1)))
return false
}
return true
}
console.log('string1 is consecutive: ' + conletters(string1))
console.log('string2 is consecutive: ' + conletters(string2))
You should definitely do it with code:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
That said, you can do better than testing all the combinations when using regexes. With lookahead expressions you can basically do "and" operation. Since you know the length you could do:
const myRegex = /(?=^(ab|bc)...$)(?=^.(ab|bc)..$)(?=^..(ab|bc).$)(?=^...(ab|bc)$)/
You will need to replace the (ab|bc) with all the possible two combinations.
For this particular case it is actually worse than testing all the possibilities (since there are only 22 possibilities) but it makes it more extensible to other situations.

Remove Any Non-Digit And Check if Formatted as Valid Number

I'm trying to figure out a regex pattern that allows a string but removes anything that is not a digit, a ., or a leading -.
I am looking for the simplest way of removing any non "number" variables from a string. This solution doesn't have to be regex.
This means that it should turn
1.203.00 -> 1.20300
-1.203.00 -> -1.20300
-1.-1 -> -1.1
.1 -> .1
3.h3 -> 3.3
4h.34 -> 4.34
44 -> 44
4h -> 4
The rule would be that the first period is a decimal point, and every following one should be removed. There should only be one minus sign in the string and it should be at the front.
I was thinking there should be a regex for it, but I just can't wrap my head around it. Most regex solutions I have figured out allow the second decimal point to remain in place.
You can use this replace approach:
In the first replace we are removing all non-digit and non-DOT characters. Only exception is first hyphen that we negative using a lookahead.
In the second replace with a callback we are removing all the DOT after first DOT.
Code & Demo:
var nums = ['..1', '1..1', '1.203.00', '-1.203.00', '-1.-1', '.1', '3.h3',
'4h.34', '4.34', '44', '4h'
]
document.writeln("<pre>")
for (i = 0; i < nums.length; i++)
document.writeln(nums[i] + " => " + nums[i].replace(/(?!^-)[^\d.]+/g, "").
replace(/^(-?\d*\.\d*)([\d.]+)$/,
function($0, $1, $2) {
return $1 + $2.replace(/[.]+/g, '');
}))
document.writeln("</pre>")
A non-regex solution, implementing a trivial single-pass parser.
Uses ES5 Array features because I like them, but will work just as well with a for-loop.
function generousParse(input) {
var sign = false, point = false;
return input.split('').filter(function(char) {
if (char.match(/[0-9]/)) {
return sign = true;
}
else if (!sign && char === '-') {
return sign = true;
}
else if (!point && char === '.') {
return point = sign = true;
}
else {
return false;
}
}).join('');
}
var inputs = ['1.203.00', '-1.203.00', '-1.-1', '.1', '3.h3', '4h.34', '4.34', '4h.-34', '44', '4h', '.-1', '1..1'];
console.log(inputs.map(generousParse));
Yes, it's longer than multiple regex replaces, but it's much easier to understand and see that it's correct.
I can do it with a regex search-and-replace. num is the string passed in.
num.replace(/[^\d\-\.]/g, '').replace(/(.)-/g, '$1').replace(/\.(\d*\.)*/, function(s) {
return '.' + s.replace(/\./g, '');
});
OK weak attempt but seems fine..
var r = /^-?\.?\d+\.?|(?=[a-z]).*|\d+/g,
str = "1.203.00\n-1.203.00\n-1.-1\n.1\n3.h3\n4h.34\n44\n4h"
sar = str.split("\n").map(s=> s.match(r).join("").replace(/[a-z]/,""));
console.log(sar);

Two equal strings representing whitespaces not equals in JS

I am encountering a problem trying to replace whitespaces in a number.
For instance, this works, i.e. it returns 27721 as expected:
alert("27 721".replace(/ /g, ""));
While - I don't know why - this does not (my browser is in french so thousand separator is a whitespace) :
function getThousandSeparator() {
var testN = 1000;
return testN.toLocaleString().replace(/\d/g,"");
}
alert("27 721".replace(new RegExp(getThousandSeparator(), "g"), ""));
And if I make the function directly return " " then it works.
Also, if you test :
console.log(getThousandSeparator() == " ");
it shows false...
Thank you in advance.
In my testing, the separator character is actually an (non-breaking space), not a real space.

Clarification of a specific regex

I attempted the CoderByte - Simple Symbols - challenge in JavaScript. From CoderByte:
Using the JavaScript language, have the function SimpleSymbols(str)
take the str parameter being passed and determine if it is an
acceptable sequence by either returning the string true or false. The
str parameter will be composed of + and = symbols with several letters
between them (ie. ++d+===+c++==a) and for the string to be true each
letter must be surrounded by a + symbol. So the string to the left
would be false. The string will not be empty and will have at least
one letter.
My solution:
function simpleSymbols(str) {
var isSymbol = true;
var output = " ";
var symbol = " ";
if (str.match(/[a-zA-Z]/).length != 0) {
for (var i = 0; i <= str.length - 1; i++) {
if ((str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') ||
(str.charAt(i) >= 'a' && str.charAt(i) <= 'z')) {
if (i != str.length - 1) {
symbol = str[--i] + str[++i] + str[++i];
var rgx = new RegExp(/\+[a-zA-Z]\+/);
if (!(rgx.test(symbol))) {
isSymbol = false;
break;
}
}
else {
isSymbol = false;
break;
}
}
}
}
else {
isSymbol = false;
}
return isSymbol;
}
This worked fine for all test cases.
On reviewing code of other submissions, I came across a submission which required only a single line of code:
return ('=' + str + '=').match(/([^\+][a-z])|([a-z][^\+])/gi) === null;
I'm having trouble understanding how the RegEx used here works. Theoretically, I understand:
g modifier => checks for all matches
i modifier => case-insensitive checking
a-z => checks the string contains only letters
\+ => refers to the plus sign
| => match either alternative1 OR alternative2
Thus, if referring to the above, I understand that there are two match conditions:
([^\+][a-z])
([a-z][^\+])
So, for a test input such as "+x+y+z+". Am I correct in understanding that the way it checks matches is as follows: +x => x+ => +y => y+ => +z => z+
Further clarification on this RegEx would be really helpful.
Thanks.
https://regex101.com/ is your friend !
Technically you are right about what you have said.
[^+] matches everything BUT the plus sign. Now the regex says "if there is a letter that is not preceded by a + or a letter that is not followed by a plus, return the regex".
But since there is "=== null", it will return true only if the above regex has not found anything.
[^\+] means any character that's not a plus. [] is a character group and a ^ at the beginning inside a character group means negate/not. It just says "does this string contain any character that's not a plus, followed by a letter a-z?" which would mean it doesn't follow the rules.

Categories

Resources