RegExp. I need to advance my expression with leading zeros - regex

I've got my RegExp: '^[0-9]{0,6}$|^[0-9]\d{0,6}[.,]\d{0,2}'.
I need to upgrade condition above to work with an input like '000'. It should format into '0.00'
There is a list of inputs and outputs that i expect to get:
Inputs:
[5555,
55.5,
55.55,
0.50,
555555.55,
000005,
005]
Outputs:
[5555,
55.5,
55.55,
0.50,
555555.55,
0.00005,
0.05]

When working with RegExps it's important to describe, in prose, what it is you want it to match, and then what you want to do with the match.
In this case your RegExp matches a string consisting entirely of 0-6 digits, or a string starting with 1-7 digits, a . or , and then 0-2 digits.
That is: either a string with digits and no ,/., or one with digits and ,/. and as many (up to 2) digits afterwards.
You then ask to convert 000 to 0.00. I'm guessing that you want to normalize numbers to no unnecessary leading zeros, and two decimal digits.
(Now with more examples, I'm guessing that a number with a leading zero and no decimal point should have decimal point added after the first zero).
I agree that using a proper number formatter is probably the way to go, but since we are talking RegExps, here's what I'd do if I had to use RegExps:
Use capture groups, so you can easily see which part matched.
Use a regexp which doesn't capture leading zeros.
Don't try to count in RegExps. Do that in code on the side (if necessary).
Something like:
final _re = RegExp(r"^\d{0,6}$|^(\d{1,7}[,.]\d{0,2})");
String format(String number) {
var match = _re.firstMatch(number);
if (match == null) return null;
var decimals = match[1];
if (decimals != null) return decimals;
var noDecimals = match[0];
if (!noDecimals.startsWith('0')) return noDecimals;
return "0.${noDecimals.substring(1)}";
}
This matches the same strings as your RegExp.

Related

Angular regex error

I'm creating a form in Angular that requires the rate field to take only numbers with 2 decimal places. My HTML is as follows:
<input type="number" class="form-control" (keypress)="_keyPress($event)" (ngModelChange)="Valuechange($event,salesorder,'Rate')" [ngModelOptions]="{standalone: true}" name="customerCode" #customerCode="ngModel" [(ngModel)]="salesorder._dto.rate" [style]="{'text-align':'right'}" />
On every keypress event I'm calling _keyPress() method as follows:
_keyPress(event: any) {
const pattern = /[0-9\+\.\ ]/;
let inputChar = String.fromCharCode(event.charCode);
if (!pattern.test(inputChar)) {
// invalid character, prevent input
event.preventDefault();
}
}
The above regex works fine but does not restrict the number to 2 decimal places. I tried with various regex but could not implement the restriction to 2 decimal places. The last regex I used to do the same is as follows:
const pattern = /[0-9]+(.[0-9]{0,2})/;
I have no much idea about regex.
You can try following regex:
const pattern = /^[0-9]*\.[0-9]{2}$/
Or you may use shorthand character class \d instead of [0-9] i.e:
const pattern = /^\d*\.\d{2}$/
Description:
[0-9]{2}$ or \d{2}$ will make sure that there are exactly 2 numbers after decimal point.
You may replace * with + if there must be at least one number before point.
To restrict the decimal place to 2 digits, you could use {2}.
{0,2} means match zero, one or two times.
[0-9]+(\.[0-9]{2})
Note
This uses an unnecessary capturing group (\.[0-9]{2}) which could be written as \.[0-9]{2}
You could also use anchors to match from the beginning ^ to the end $:
^[0-9]+(\.[0-9]{2})$
or
^[0-9]+\.[0-9]{2}$
var pattern = /^[0-9]+(\.[0-9]{2})$/;
var inputs = [
"22.65",
"22.6",
"22.656"
];
for (var i = 0; i< inputs.length; i++) {
console.log(pattern.test(inputs[i]))
}

Parsing a numerical string into a numerical vector with regex

I have a set of numerical strings (used in filenames) which I would like to parse into a vectors
Here is an example
-0_01_-1_0_23_0_52_-0_25
Which should be parse into
-0.01 -1 0.23 0.52 -0.25
The rules are:
There are 5 numbers between [-1, 1]
Numbers are separated by '_'
Decimal point is replaced by '_'.
integer numbers {-1, 0, 1}, don't have a decimal point
How can I use regex (preferably matlab) to convert the string into a vector?
I tried some regex expression, but got stuck with dealing with the integer rule.
Use this code:
a = '-0_01_-1_0_23_0_52_-0_25';
a = strrep(a, '0_', '0.');
res = regexp(a, '(-?[0-9]+(?:\.[0-9]+)?)','match');
res = cellfun(#str2num, res)
First, replace 0_ with 0, and then use the -?[0-9]+(?:,[0-9]+)? regex to match the numbers only.
The regex matches an optional -, then 1+ digits, and then an optional substring with , and 1+ digits.

Return a defined range of characters in Go

Let's say we have a converted float to a string:
"24.22334455667"
I want to just return 6 of the digits on the right of the decimal
I can get all digits, after the decimal this way:
re2 := regexp.MustCompile(`[!.]([\d]+)$`)
But I want only the first 6 digits after the decimal but this returns nothing:
re2 := regexp.MustCompile(`[!.]([\d]{1,6})$`)
How can I do this? I could not find an example of using [\d]{1,6}
Thanks
Alternatively...
func DecimalPlaces(decimalStr string, places int) string {
location := strings.Index(decimalStr, ".")
if location == -1 {
return ""
}
return decimalStr[location+1 : min(location+1+places, len(decimalStr))]
}
Where min is just a simple function to find the minimum of two integers.
Regular expressions seem a bit heavyweight for this sort of simple string manipulation.
Playground
You must remove the end of the line anchor $ since it won't be a line end after exactly 6 digits. For to capture exactly 6 digits, the quantifier must be
re2 := regexp.MustCompile(`[!.](\d{6})`)
Note that, this would also the digits which exists next to !. If you don't want this behaviour, you must remove the ! from the charcater class like
re2 := regexp.MustCompile(`[.](\d{6})`)
or
For to capture digits ranges from 1 to 6,
re2 := regexp.MustCompile(`[!.](\d{1,6})`)

How to format a string to replace all existing number inside a string to prefix with leading zero using regex

Anyone knows how to use regex to convert a string with characters and numbers to prefix with leading zero for each occurance of a number inside the string.
Eg ABC123 -> ABC000100020003
BCD02 - > BCD00000002
CD1A2 - > CD0001A0002
i.e for each occurance of a number it will prefix with leading zeros (total 4 digit for each occurance of a number)
Other characters to remain the same.
search /(\d)/g
and replace with 000\1
will do it.
demo here : http://regex101.com/r/aB8iE9
javascript demo here:
var str = "ABC123";
var res = str.replace(/(\d)/g, '000$1');
console.log(res);

Regular Expression to find numbers with same digits in different order

I have been looking for a regular expression with Google for an hour or so now and can't seem to work this one out :(
If I have a number, say:
2345
and I want to find any other number with the same digits but in a different order, like this:
2345
For example, I match
3245 or 5432 (same digits but different order)
How would I write a regular expression for this?
There is an "elegant" way to do it with a single regex:
^(?:2()|3()|4()|5()){4}\1\2\3\4$
will match the digits 2, 3, 4 and 5 in any order. All four are required.
Explanation:
(?:2()|3()|4()|5()) matches one of the numbers 2, 3, 4, or 5. The trick is now that the capturing parentheses match an empty string after matching a number (which always succeeds).
{4} requires that this happens four times.
\1\2\3\4 then requires that all four backreferences have participated in the match - which they do if and only if each number has occurred once. Since \1\2\3\4 matches an empty string, it will always match as long as the previous condition is true.
For five digits, you'd need
^(?:2()|3()|4()|5()|6()){5}\1\2\3\4\5$
etc...
This will work in nearly any regex flavor except JavaScript.
I don't think a regex is appropriate. So here is an idea that is faster than a regex for this situation:
check string lengths, if they are different, return false
make a hash from the character (digits in your case) to integers for counting
loop through the characters of your first string:
increment the counter for that character: hash[character]++
loop through the characters of the second string:
decrement the counter for that character: hash[character]--
break if any count is negative (or nonexistent)
loop through the entries, making sure each is 0:
if all are 0, return true
else return false
EDIT: Java Code (I'm using Character for this example, not exactly Unicode friendly, but it's the idea that matters now):
import java.util.*;
public class Test
{
public boolean isSimilar(String first, String second)
{
if(first.length() != second.length())
return false;
HashMap<Character, Integer> hash = new HashMap<Character, Integer>();
for(char c : first.toCharArray())
{
if(hash.get(c) != null)
{
int count = hash.get(c);
count++;
hash.put(c, count);
}
else
{
hash.put(c, 1);
}
}
for(char c : second.toCharArray())
{
if(hash.get(c) != null)
{
int count = hash.get(c);
count--;
if(count < 0)
return false;
hash.put(c, count);
}
else
{
return false;
}
}
for(Integer i : hash.values())
{
if(i.intValue()!=0)
return false;
}
return true;
}
public static void main(String ... args)
{
//tested to print false
System.out.println(new Test().isSimilar("23445", "5432"));
//tested to print true
System.out.println(new Test().isSimilar("2345", "5432"));
}
}
This will also work for comparing letters or other character sequences, like "god" and "dog".
Put the digits of each number in two arrays, sort the arrays, find out if they hold the same digits at the same indices.
RegExes are not the right tool for this task.
You could do something like this to ensure the right characters and length
[2345]{4}
Ensuring they only exist once is trickier and why this is not suited to regexes
(?=.*2.*)(?=.*3.*)(?=.*4.*)(?=.*5.*)[2345]{4}
The simplest regular expression is just all 24 permutations added up via the or operator:
/2345|3245|5432|.../;
That said, you don't want to solve this with a regex if you can get away with it. A single pass through the two numbers as strings is probably better:
1. Check the string length of both strings - if they're different you're done.
2. Build a hash of all the digits from the number you're matching against.
3. Run through the digits in the number you're checking. If you hit a match in the hash, mark it as used. Keep going until you don't get an unused match in the hash or run out of items.
I think it's very simple to achieve if you're OK with matching a number that doesn't use all of the digits. E.g. if you have a number 1234 and you accept a match with the number of 1111 to return TRUE;
Let me use PHP for an example as you haven't specified what language you use.
$my_num = 1245;
$my_pattern = '/[' . $my_num . ']{4}/'; // this resolves to pattern: /[1245]{4}/
$my_pattern2 = '/[' . $my_num . ']+/'; // as above but numbers can by of any length
$number1 = 4521;
$match = preg_match($my_pattern, $number1); // will return TRUE
$number2 = 2222444111;
$match2 = preg_match($my_pattern2, $number2); // will return TRUE
$number3 = 888;
$match3 = preg_match($my_pattern, $number3); // will return FALSE
$match4 = preg_match($my_pattern2, $number3); // will return FALSE
Something similar will work in Perl as well.
Regular expressions are not appropriate for this purpose. Here is a Perl script:
#/usr/bin/perl
use strict;
use warnings;
my $src = '2345';
my #test = qw( 3245 5432 5542 1234 12345 );
my $canonical = canonicalize( $src );
for my $candidate ( #test ) {
next unless $canonical eq canonicalize( $candidate );
print "$src and $candidate consist of the same digits\n";
}
sub canonicalize { join '', sort split //, $_[0] }
Output:
C:\Temp> ks
2345 and 3245 consist of the same digits
2345 and 5432 consist of the same digits