Regular expression to ignore the numbers after length reaches 10 - javascript

I want number in this format
(123)-456-7890
The maximum length assigned is 10.
The regular expression used to obtain the above format is:
if (onlyNums.length === 10) {
const number = onlyNums.replace(/(\d{3})(\d{3})(\d{4})/, '($1) -$2-$3');
If length>10 I want the above format for the number and to ignore the rest of the digits(right trim).
How can I do that?

If you remove the if condition and add a "catch-all" regex .* at the end, it will ignore whatever comes after the 10th digit:
const number = onlyNums.replace(/(\d{3})(\d{3})(\d{4}).*/, '($1) -$2-$3');
This assumes that onlyNums actually contains nothing but digits (and at least 10 of them). Otherwise, the result might be unexpected.
Test it live on regex101.com.

Related

Check if no unicode character is associated with a number Javascript

I am making a base converter that can convert any number in any base to the same number in any other base. Since the bases could be any number the result could have digits that represent a number greater than 10. In order to have only one character correspond to each digit in the final result, I plan to assign Unicode characters to each digit corresponding to a value greater than 10 by using String.fromCharCode(Base 10 number digit represents). However, I noticed that there was a problem with this method; It seems as if a lot of the values are blank when outputted onto the HTML webpage or only output an empty box that looks like this: ⯣. When I tried to see if the value of the Unicode character equaled the empty box or an empty string by using an if statement, it always seemed to return false, even when the Unicode character associated with the digit returned the same empty box. Please may you help me understand why this is, and how I can construct the if statement such that it will work like I want it to?
You could try this:
function convertToDecimal(num, base) {
return window.parseInt(num.toString(), base);
}
const binary = 10;
const base = 2;
console.log("Decimal version:", convertToDecimal(binary, base))

Regex for single digits and single digit with decimal only

I'm having a hard time coming up with the most suitable regex for my needs.
I want a regex that only validates numbers from 1-8, with or without a decimal point
1 // Valid
3 // Valid
8 // Valid
2.00 // Valid
4.45 // Valid
7.60 // Valid
9 // Invalid
10 // Invalid
9.00 // Invalid
50.40 // invalid
So far this is what I came up with, but ^([0-8]$\.?[0-8]*|\.[0-8]+) but this only accepts numbers from 1-8, and nothing with a decimal. Can someone kindly provide a suitable regex for this example?
I guess it would be better to limit regex to string parsing. My best approach would be to parse a valid number from the string and then convert it to number before doing any validation on its value as being < x
But if you really want to go via regex (and it will be hard to change in case) would be with something like:
^0*([0-7](\.\d+)?|8)$
It matches any number between 0 and 8 ... decimal point is allowed if followed by numbers and the highest valid number like that would be 7.999999999... followed by the next valid integer number being 8.
Trailing zeros are considered.

How to parse a string containing text for a number/float in javascript?

I'm trying to build a javascript function capable of parsing a sentence and returning a number.
Here is a jsFiddle I've setup for the test cases below -
'I have 1 pound' -> 1
'I have £3.50 to spend' -> 3.50
'I have 23.00 pounds' -> 23
'£27.33' -> 27.33
'$4345.85' -> 4345.85
'3.00' -> 3
'7.0' -> 7
'Should have 2.0.' -> 2
'Should have 15.20.' -> 15.20
'3.15' -> 3.15
'I only have 5, not great.' -> 5
' 34.23' -> 34.23
'sdfg545.14sdfg' -> 545.14
'Yesterday I spent £235468.13.
Today I want to spend less.' -> 235468.13
'Yesterday I spent
340pounds.' -> 340
'I spent £14.52 today, £17.30 tomorrow' -> 14.52
'I have 0 trees, £11.33 tomorrow' -> 0
16&17 indicate that it should find the first number. I understand that some of the test cases may be tough but I welcome anything that gets me reasonable coverage.
Here is the format I'm using for my function
function parseSentenceForNumber(sentence){
return number; //The number from the string
}
I think I could get 60-80% of the way myself, but I expect a regular expression might be the best solution here and I've never been great at them. Hopefully I have enough test cases but feel free to add any I might of missed.
Your help is much appreciated.
**UPDATE**
Loads of working answers and I need to spend some time looking at them in more detail. Mike Samuel mentioned commas and .5 which leads me to add another couple of test cases
18.'I have 1,000 pound' -> 1000
19.'.5' -> 0.5
And jsalonen mentioned adding test case for no numbers
20.'This sentence contains no numbers' -> null
Here is the updated fiddle using jsalonen's solution, without my changes in spec I'd be 100% there, with the changes I'm 95%. Can anyone offer a solution to number 18 with commas?
**UPDATE**
I added a statement to strip out commas to jsalonen's function and I'm at 100%.
Here is the final function
function parseSentenceForNumber(sentence){
var matches = sentence.replace(/,/g, '').match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/);
return matches && matches[0] || null;
}
And the final Fiddle
Really appreciate the help and I have improved my regular expression knowledge along the way. Thanks
Answer that matches all negative and positive numbers with any number of digits:
function parseSentenceForNumber(sentence){
var matches = sentence.match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/);
return matches && matches[0] || null;
}
Consider adding negative test cases too, like testing what happens when a string does not have numbers:
test("Test parseSentenceForNumber('This sentence contains no numbers')", function() {
equal( parseSentenceForNumber('This sentence contains no numbers'), null );
});
Full fiddle: http://jsfiddle.net/cvw8g/6/
The regular expression:
\d+(?:\.\d+)?
should do it.
\d+ matches a sequence of digits.
.\d+ matches a decimal point followed by digits.
(?:...)? makes that group optional
This doesn't deal with the special case where the fraction is all zeroes, and you don't want the fraction included in the result, that's difficult with a regexp (I'm not sure if it can even be done, although I'm willing to be proven wrong). It should be easier to handle that after matching the number with the decimal in it.
Once you've matched the number in the string, use parseFloat() to convert it to a number, and toFixed(2) to get 2 decimal places.
The general form of a number in computer readable form is:
/[+\-]?((?:[1-9]\d*|0)(?:\.\d*)?|\.\d+)([eE][+-]?\d+)?/
based on the grammar
number := optional_sign (integer optional_fraction | fraction) optional_exponent;
optional_sign := '+' | '0' | ε;
integer := decimal_digit optional_integer;
optional_integer := integer | ε;
optional_fraction := '.' optional_integer | ε;
fraction := '.' integer;
optional_exponent := ('e' | 'E') optional_sign integer;
so you can do
function parseSentenceForNumber(sentence){
var match = sentence.match(
/[+\-]?((?:[1-9]\d*|0)(?:\.\d*)?|\.\d+)([eE][+-]?\d+)?/);
return match ? +match[0] : null; //The number from the string
}
but this doesn't account for
Locales that use fraction separators other than '.' as in "π is 3,14159..."
Commas to separate groups of digits as in 1,000,000
Fractions
Percentages
Natural language descriptions like "a dozen" or "15 million pounds"
To handle those cases you might search for "entity extraction" since that's the overarching field that tries to find phrases that specify structured data within unstructured text.
One more possible regex:
/\d+\.?\d{0,2}/
This means:
\d: one or more digits
\.?: zero or one period
d{0,2} up to 2 digits
http://jsfiddle.net/cvw8g/7/
No regex, uses parse aswell (so will return NaN if no number found).
Finds the first number in the string, then attempt to parse it from that point.
Passes all of your tests, and returns a number, not a string, so you can immediately use it for comparisons or arithmatic.
function parseSentenceForNumber(str) {
//tacked on to support the new "1,000" -> 1000 case
str = str.replace(',', '');
var index;
//find the first digit
for (index = 0; index < str.length; ++index) {
if (str.charAt(index) >= '0' && str.charAt(index) <= '9')
break;
}
//checking for negative or decimal point (for '.5')
if (index > 0 && (
str.charAt(index - 1) == '-' ||
str.charAt(index - 1) == '.'
))
//go back one character
--index;
//get the rest of the string, accepted by native parseFloat
return parseFloat(str.substring(index));
}
Passes all tests and I think it is a lot more readable:
function parseSentenceForNumber(sentence){
return parseFloat(sentence.replace(/,(?=\d)/g,"").match(/-?\.?\d.*/g));
}
...well almost all tests: it returns 'NaN' instead of 'null' when no number is in sentence. But I think 'NaN' is more informative than a simple 'null'.
Here is the jsFiddle: http://jsfiddle.net/55AXf/

what's wrong with this regular expression (if else regex)

What I want is, there is a textbox with maximum length of 5. The values allowed are..
any integer // for example 1, 3, 9, 9239 all are valid
real number, with exaclty one point after decimal // eg. 1.2, 93.7 valid and 61.37, 55.67 invalid
it is also allowed to enter only decimal and a digit after that, that is .7 is valid entry (would be considered as 0.7)
I found this page, http://www.regular-expressions.info/refadv.html
So what I thought is that
There is a digit
If there is a digit and a decimal after that, there must be one number after that
If there is no digit there must be a decimal and a digit after that
So, the regex I made is..
a single digit one or more => /d+
an optional decimal point followed by exactly one digit => (?:[.]\d{1})?
if first condition matches => (?(first condition) => (?((?<=\d+)
then, match the option decimal and one exact digit =>(?((?<=\d+)(?:[.]\d{1})?
else => |
find if there is a decimal and one exact digit => (?:[.]\d{1}){1}
check the whole condition globally => /gm
overall expression =>
(?(?<=\d+)(?:[.]\d{1}){1}|(?:[.]\d{1}){1})+/gm
But it doesn't outputs anything..
Here's the fiddle
http://jsfiddle.net/Fs6aq/4/
ps: the pattern1 and pattern2 there, are related to my previous question.
Maybe you are complicating things too much. I did a quick test and unless I'm missing something this regex seems to work fine:
/^\d*\.?\d$/
Demo: http://jsbin.com/esihex/4/edit
Edit: To check the length you can do it without regex:
if ( value.replace('.','').length <= 5 && regex.test( value ) ) {
...
}
Notice that I used replace to remove the dots so they don't count as characters when getting the length.
You can try the following pattern:
/^\d{0,4}\.?\d$/
It seems to fulfil all your requirements:
> /^\d{0,4}\.?\d$/.test(".4")
true
> /^\d{0,4}\.?\d$/.test(".45")
false
> /^\d{0,4}\.?\d$/.test("1234.4")
true
> /^\d{0,4}\.?\d$/.test("12345.4")
false
> /^\d{0,4}\.?\d$/.test("12345")
true
> /^\d{0,4}\.?\d$/.test("123456")
false
This pattern assumes that the number can have a maximum of five digits and an optional decimal point.
If the maximum length of five includes the optional decimal point then the pattern is slightly more complex:
/^(?:\d{1,5}|\d{0,3}\.\d)$/
The first part of the group deals with integer numbers of the required length, the second option of the group deals with real numbers which maximum length (including the decimal point) is five.
Consider this code:
var checkedString = "45.3 fsd fsd fsdfsd 673.24 fsd63.2ds 32.2 ds 32 ds 44 fasd 432 235f d653 dsdfs";
checkedString = " "+checkedString;
var results = checkedString.match(/[\s]{1}(\d+\.*\d{1})(?![\d\.\w])+/gm);
results.map(function(result) {
return result.trim();
});
Couldn't make it in other way because in JS (?<= (lookbehind) regexp is not working.
This will be returned:
["45.3","32.2","32","44","432"]
So probably it's what you've expected.
I don't know what are you trying to do with those conditionals in your regex. I also looked at your jsfiddle, which outputs nothing for me. But I made a two versions of a regex that matches the correct values for the textbox, which are ^(?!(.{6,}))(?:[1-9]\d*)*(?:\.\d*[1-9])?$ and ^(?!(.{6,}))(?:\d*)*(?:\.\d*)?$.
The first disallows to start with zero, or end with zero after the decimal.
Comment if you need explanation of the regex.

Javascript Checking for NaN - Results not as expected

I have an application that reads in a number via ajax, the number is hexadecimal and I parse it and convert to decimal.
The numbers come in through a wireless serial link and are not 100% reliable so I need to check them before I start processing the data. The numbers take the form ****025781610403e5**** for example. The **** is just a way of checking the start and end of the number that I have used in the past with non web based projects and could be changed.
Anyway to my question at last: As part of error checking I thought I would check for NaN as I do get NaN errors when I have been testing but while *1234 gives a positive NaN 12**34 does not, why is that? and what else can I do to test?
Here is some of the code I have used, please note I am fairly new to javascript.
function readSliceConvert()
{
functionReadForm()
testVal = hexString.slice(4,18);
document.getElementById("battDb4").innerHTML=testVal;
testNum1 = h2d(testVal)
document.getElementById("battDb5").innerHTML=testNum1.toString();
testNum2 = parseInt(testVal);
document.getElementById("battDb6").innerHTML=testNum2.toString();
if (isNaN(testNum2))
{
errorCount++;
document.getElementById("battDb3").innerHTML=errorCount.toString();
document.getElementById("battDb4").innerHTML=testVal;
return;
}
}
That's because you are using parseInt, it will silently ignore characters at the end of the string when there are some digit in the beginning of the string that it can parse.
I don't know what your h2d function is doing, but it seems that you are converting the hexadecimal string to a number, then to a string in decimal form, then back to a number. I don't see any reason why the output of parsing the hexadecimal string couldn't be a number.
For example like this, returning null if the parsing fails:
function h2i(str) {
var num = 0;
var digits = "0123456789abcdef";
str = str.toLowerCase();
for (var i = 0; i < str.length; i++) {
var n = digits.indexOf(str.substr(i, 1));
if (n == -1) return null;
num = num * 16 + n;
}
return num;
}
Demo: http://jsfiddle.net/Guffa/6yAaP/
Usage:
testVal = hexString.slice(4,18);
document.getElementById("battDb4").innerHTML = testVal;
testNum = h2i(testVal)
document.getElementById("battDb5").innerHTML = testNum.toString();
if (testNum == null)
{
errorCount++;
document.getElementById("battDb3").innerHTML = errorCount.toString();
document.getElementById("battDb4").innerHTML = testVal;
return;
}
Do you know what parseInt() does?
From MDN
parseInt is a top-level function and is not associated with any
object.
The parseInt function converts its first argument to a string, parses
it, and returns an integer or NaN. If not NaN, the returned value will
be the decimal integer representation of the first argument taken as a
number in the specified radix (base). For example, a radix of 10
indicates to convert from a decimal number, 8 octal, 16 hexadecimal,
and so on. For radices above 10, the letters of the alphabet indicate
numerals greater than 9. For example, for hexadecimal numbers (base
16), A through F are used.
If parseInt encounters a character that is not a numeral in the
specified radix, it ignores it and all succeeding characters and
returns the integer value parsed up to that point. parseInt truncates
numbers to integer values. Leading and trailing spaces are allowed.
Run the code in the console
console.log( parseInt("12**34",10) );
So you are running isNaN against a number since parseInt returns 12.
When you have the * as the first character, there are no leading numbers to return.
console.log( parseInt("*1234",10) );
You're seeing weird behaviour because isNan is broken (see the mozilla docs for details).
A better way to test your data is correctly formatted would be a quick regular expression, like serial.test(/^\d+$/), which will succeed if the entire serial is entirely numeric, or serial.test(/^\*{4}\d+\*{4}$/) which will succeed if the serial is four asterisks, followed by one or more number, followed by another four asterisks.
Update: #Guffa's answer is correct, and should be accepted, but I'll leave this here as I think there's a valid argument in the bigger picture that you could better accomplish what you're trying to do with a regular expression.
Running test on the string executes the supplied regular expression, and returns true if it matches the string.
Regular expressions are just patterns describing text, which can be incredibly complex or as simple as the example I've given (\d+ means match a number (\d) one or more times (+), with anchors for the beginning (^) and end ($) of the string to indicate that we want to match the whole string, not just part of it. They're ridiculously useful, so it's almost certainly worth taking the time to learn the basics of how they work, and expand you knowledge over time. There's a great tutorial on regular-expressions.info that'll get you started in no time.

Categories