I have a pricelist that I would like to 'normalize', using the Javascript flavor of Regex.
Sample input:
1
1,99
1.99
10
100
5999 dollars
2 USD
$2,99
Our price 2.99
Price: $ 20
200 $
20,-
6 999 USD
Desired output:
1
1,99
1.99
10
100
5999
2
2,99
2.99
20
200
20
6999
I am getting rather good results with /([0-9.,\s]+)/ but I've got two problems:
The last sample line returns 6 instead of 6 999. I am not sure if it's possible to "remove" the space, preferably I would like to get 6999 but 6 999 is close enough.
Second last line returns 20, (which is logical since I include commas) but rather want 20 only in these cases.
Here is a fiddle: http://jsfiddle.net/8h8Tk/
If you really wanted to normalize your input, I would suggest you choose either , or . for your decimal value separator. However, if not, the jsfiddle above gives the correct output.
var output = input.replace(/[^0-9\.,\n]|,[^0-9]/g, "");
All it does is remove the characters you don't want.
Here's a version that is straight out of Match (or replace) a pattern except in situations s1, s2, s3 etc
The regex: (?:\d|[.,](?=\d))+|(\w+|.)
The left side of the alternation matches characters we want: digits, or dots and commas followed by digits. The right side matches and captures word characters or a single character, and we know these are not characters we want because they were not matched by the expression on the left.
When Group 1 is set, we replace with an empty string.
See the output in the online demo
<script>
var subject = "1 \n\
1,99 \n\
1.99 \n\
10 \n\
100 \n\
5 999 \n\
2 USD \n\
$2,99 \n\
Our price 2.99 \n\
Price: $ 20 \n\
200 $ \n\
20,- \n\
6 999 USD";
var regex = /(?:\d|[.,](?=\d))+|(\w+|.)/g;
replaced = subject.replace(regex, function(m, group1) {
if (group1 == "" ) return m;
else return "";
});
document.write("<pre>");
document.write(replaced);
document.write("</pre>");
</script>
The Output
1
1,99
1.99
10
100
5999
2
2,99
2.99
20
200
20
6999
If you don't mind doing it in two steps, first convert all commas to dots:
x = x.replace(/,/g, '.')
Then get rid of everything else:
x = x.replace(/[^.|0-9]+/g,'')
Replace what you don't want:
result = subject.replace(/[^\d.,]+/g, "");
How about /((?:[\d.,\s]+)?[\d]+)\b/g It extends from your original version
Related
I'm attempting to do some validation a price field. I would like to check if the price entered into the price field ends in .99
I've attempted find posts about this but I can't find examples for decimal numbers only whole numbers. I tried to check by doing price % 1 but it isnt consistent as the price increases by 10, 20 etc.
Is there a quick way to check if all numbers end in .99?
const price = 9.99
console.log(price % 1)
Floating point math is inherently imprecise. The actual mathematical expression price - 9 will get those extra 0s and a 2 too.
Best you could do is convert to a string with fixed precision (rounding off any extraneous precision; for a price in dollars, you'd only need two digits, but you might go to three or more to verify the price entered didn't end with nonsense fractions of a cent) and perform a string test, e.g.
price.toFixed(2).endsWith('.99')
which doesn't try to perform math on price at all, it just rounds off to two digits after the decimal place to produce a string, then checks if the string ends with .99.
You can try regular expression as well. See following code for example:
function testRegex() {
var re = /^[0-9]*[.](99)$/;
var val = document.getElementById("inputValue").value;
if(re.exec(val)) {
document.getElementById("result").innerText = "Found match!!!";
} else {
document.getElementById("result").innerText = "Found no match!!!";
}
}
<input type="text" id="inputValue" value="" onkeyup="testRegex()" />
<div id="result"></div>
You can perform that validation using the following regular expression:
/\.99$/
First, we try to match an explicit . by escaping it with a backlash. Then, the next two characters must be 99, and then the string end must occur for the successful match. We check that with $. For example,
prices = [0.99, 0.0099, 1.99, 2.99, 3.98, 4.01];
for (const price of prices) {
if (/\.99$/.test(price.toString())) {
console.log(`${price} ends with .99`);
}
}
will print:
0.99 ends with .99
1.99 ends with .99
2.99 ends with .99
I am trying to split a string which is of the following format -
text = "some random words 22 minutes go some text that follows". I am only concerned about "some random words".
The text can have 'minute' or 'hour' or 'hours' in it. I want to split and get the string that is before the digits. I cannot split based on digits only because the initial part can have digits too.
I tried to handle this with split and if conditions. But those are not fast enough. I am struggling to deal this with typescript regex group. Any suggestions would be very helpful
The function that I used was -
export function splitstring(msg: string): string
{
if (msg.includes('minute'))
{
return msg.toLowerCase().split('minute')[0];
}
if (msg.includes('minutes'))
{
return msg.toLowerCase().split('minutes')[0];
}
if (msg.includes('hour'))
{
return msg.toLowerCase().split('hour')[0];
}
if (msg.includes('hours'))
{
return msg.toLowerCase().split('hours')[0];
}
return msg;
}
Sounds like you can use .match(/(.*)\W\d+\W(minute|hour)/)[1]
var text = "some random words 22 minutes go some text that follows";
console.log(
text.match(/(.*)\W\d+\W(minute|hour)/)[1]
)
var text = "some random words 22 inute go some 12 hours text that follows";
console.log(
text.match(/(.*)\W\d+\W(minute|hour)/)[1]
)
var text = "some 18 random words 22 minutes go 11 some text that follows";
console.log(
text.match(/(.*)\W\d+\W(minute|hour)/)[1]
)
I have many strings like this:
0001, 0002, ..., 0010, 0011, ..., 0100, 0101,...
I would like these to become like this:
1, 2, ..., 10, 11, ..., 100, 101, ...
So I would like to remove all the 0 chars before a different char is present.
I tried with
.replace(/0/g, '')
But of course then it also removes the 0 chars after. Therefore for example 0010 becomes 1 instead of 10. Can you please help me?
You can do
.replace(/\d+/g, function(v){ return +v })
This is the shortes Solution
"0001".replace(/^0+/,""); // => 1
...
// Tested on Win7 Chrome 44+
^ ... starting of the String
0+ ... At least one 0
P.s.: test Regex on pages likes: https://regex101.com/ or https://www.debuggex.com
Update 1:
For one long String
"0001, 0002, 0010, 0011, 0100, 0101".replace(/(^|\s)0+/g,"") // => 1, 2, 10, 11, 100, 101
// Tested on Win7 Chrome 44+
Examples:
// short Strings
var values = ['0001', '0002','0010', '0011','0100','0101'];
for(var idx in values){
document.write(values[idx] + " -> "+values[idx].replace(/^0+/,"") + "<br/>");
}
// one long String
document.write("0001, 0002, 0010, 0011, 0100, 0101".replace(/(^|\s)0+/g,""));
Previously answered here.
.replace(/^0+(?!$)/, '')
Functionally the same as winner_joiner's answer, with the exception that this particular regex won't return a completely empty string should the input consist entirely of zeroes.
Use regex as /(^|,\s*)0+/g it will select 0's at beginning or followed by , and space
document.write('0001, 0002, ..., 0010, 0011, ..., 0100, 0101,...'.replace(/(^|,\s*)0+/g,'$1'))
Explanation :
(^|,\s*)0+
Debuggex Demo
var text='00101';
var result=parseInt(text);
Lets say I have an amount in string format like this:
amount = '12,000.00'
I want to convert it into a Number (Javascript) or a float.
parseFloat(amount) // this gives me 12 as a result
Number(amount) // this gives me NaN as a result
Other solution I thought was this:
parseFloat(amount.replace(/[,]/g, ''))
This works fine. But the problem here is the Locale.
This would fail when the amount is € 12000,00.
Here ',' has altogether a different meaning.
I looked around for a good solution but couldn't. I am looking for a generalized solution.
This is not that easy, as you can't exactly know what's the delimiter for thousands and what for the decimal part
Consider "12.000.000" is it 12000.000 === 12000 or 12000000?
But if you would set the requirement that the last delimiter is always the decimal delimiter -
meaning if at least one delimiter is given, the last one has to be the decimal delimiter, *if the digits following, don't exceed a defined length.
Then you could try the following
Edit
(see the revs if you're interested in the old function)
I put in the ability to define the max length of digits after the last delimiter "," or "." up until it is treated as float, after that its returned as integer
var amounts = ["12000","12.000,00", "12,000.00", "12,000,01", "12.000.02", "12,000,001"];
formatMoney.maxDecLength = 3; //Set to Infinity o.s. to disable it
function formatMoney(a) {
var nums = a.split(/[,\.]/);
var ret = [nums.slice(0, nums.length - 1).join("")];
if (nums.length < 2) return +nums[0];
ret.push(nums[nums.length - 1]);
return +(ret.join(nums[nums.length - 1].length < formatMoney.maxDecLength ? "." : ""));
}
for ( var i=0,j;j=amounts[i];i++)
console.log (j + " -> " +formatMoney(j));
Gives the output:
"12000 -> 12000"
"12.000,00 -> 12000"
"12,000.00 -> 12000"
"12,000,01 -> 12000.01"
"12.000.02 -> 12000.02"
"12,000,001 -> 12000001" //as you can see after the last "," there are 3 digits and its treated as integer
Another JSBin
You can get the local decimal delimiter in this manner:
1.1.toLocaleString().substr(1,1)
Before parse float, you could make sure the string contains nothing but numbers, possibly a minus sign, and the local decimal delimiter.
The truth is, you'll never know the format. 12,345. Is that 12345, or another locale version if 12.345?
However, if you have consistent decimals, then you'd be able to use the lastIndexOf function on a comma and a period will reveal the decimal position and character.
var price = '12,345.67';
var lastPeriod = price.lastIndexOf('.');
var lastComma = price.lastIndexOf(',');
if (lastComma != -1 && lastComma > lastPeriod) {
decimalCharacter = ',';
} else {
decimalCharacter = '.';
}
console.log(decimalCharacter); //. or , based on how the price string looks - see below
If price is 12,345.67, decimalCharacter will be .. If it's 12.345,67, it'll be returned as ,.
I found Count characters/sms using jQuery, but it does not support international characters such as Chinese, Japanese, Thai, etc.
var $remaining = $('#remaining'),
$messages = $remaining.next();
$('#message').keyup(function(){
var chars = this.value.length,
messages = Math.ceil(chars / 160),
remaining = messages * 160 - (chars % (messages * 160) || messages * 160);
$remaining.text(remaining + ' characters remaining');
$messages.text(messages + ' message(s)');
});
Here are some examples of incorrect character counts:
您好,請問你吃飯了嗎? << 11 characters
สวัสดีคุณกินหรือ? << 17 characters
こんにちは、あなたは食べていますか? << 18 characters
안녕하세요, 당신이 먹는 거죠? << 17 characters
हैलो, आप खाते हैं? << 18 characters
Добры дзень, вы ясьце? << 22 characters
How can I make this work with non-ASCII characters?
You can't really count in "characters" here. According to the SMS article on Wikipedia one of three different encodings are used for SMS (7-bit GSM, 8-bit GSM and UTF-16). So first you'll need to know/decide which encoding you'll be using.
If you know you'll always be using UTF-16, then you can count the number of 16-bit code units a string will take up. A standard SMS can consist of 70 16-bit code units. But this will limit messages in Latin characters to 70, too. So if you want to use the full 160 characters (with 7-bit encoding) or 140 characters (with 8-bit encoding) for Latin characters, then you'll need to distinguish between the three cases.
Example for counting UTF-16 16-bit code units:
var message = "您好,請問你吃飯了嗎?";
var utf16codeUnits = 0;
for (var i = 0, len = message.length; i < len; i++) {
utf16codeUnits += message.charCodeAt(i) < 0x10000 ? 1 : 2;
}
BTW, this will come up with then same numbers you posted as "incorrect", so you'll need to explain why you consider them incorrect.
EDIT
Despite being accepted already I quickly hacked up a function that correctly (as far as I can say) calculates the GSM 7-bit (if possible) and UTF-16 sizes of a SMS message: http://jsfiddle.net/puKJb/