Last active
August 25, 2020 11:13
-
-
Save GataullinRR/31d0a26d46d088fc2c9356040f1039a1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Globalization; | |
| using System.Linq; | |
| using System.Text; | |
| string GenerateIsMoreThanRegexp(double value, bool isInclusive = true, bool isComma = false, int minDecimals = 2, int maxDecimals = 3) | |
| { | |
| if (minDecimals < 1 || maxDecimals < minDecimals) // So the dot must be present | |
| { | |
| throw new NotSupportedException(); | |
| } | |
| var operandParts = value.ToString(CultureInfo.InvariantCulture).Split('.'); | |
| var wholePart = operandParts[0]; | |
| var decimalPart = operandParts.Length == 2 | |
| ? operandParts[1] | |
| : "0"; | |
| if (decimalPart.Length > maxDecimals) | |
| { | |
| throw new ArgumentOutOfRangeException(); | |
| } | |
| decimalPart = decimalPart + new string('0', | |
| decimalPart.Length < maxDecimals | |
| ? maxDecimals - decimalPart.Length | |
| : 0); | |
| var sb = new StringBuilder(); | |
| var separator = isComma ? "," : "\\."; | |
| var wholePartSemanticalLength = wholePart == "0" ? 0 : wholePart.Length; | |
| if (wholePartSemanticalLength != 0) // No duplicate match regexp! | |
| { | |
| // Mored digits => higher | |
| sb.Append($@"|^[1-9]\d{{{wholePartSemanticalLength},}}{separator}\d{{{minDecimals},{maxDecimals}}}$"); | |
| } | |
| for (int i = 0; i < wholePart.Length; i++) | |
| { | |
| var elapsedLength = wholePart.Length - i; | |
| var subPart = wholePart[0..i]; | |
| var next = int.Parse(wholePart[i..(i + 1)]); | |
| if (next < 9) | |
| { | |
| sb.Append($@"|^{subPart}[{next + 1}-9]\d{{{elapsedLength - 1},}}{separator}\d{{{minDecimals},{maxDecimals}}}$"); | |
| } | |
| } | |
| for (int i = 0; i < decimalPart.Length; i++) // Two loops are more understandable than one (I guess so) | |
| { | |
| var subPart = decimalPart[0..i]; | |
| var next = int.Parse(decimalPart[i..(i + 1)]); | |
| if (next < 9) | |
| { | |
| var addToMin = i < minDecimals ? minDecimals - i - 1 : 0; | |
| var addToMax = maxDecimals - i - 1; // Already checked | |
| sb.Append($@"|^{wholePart}{separator}{subPart}[{next + 1}-9]\d{{{addToMin},{addToMax}}}$"); | |
| } | |
| } | |
| if (isInclusive) | |
| { | |
| var nonZeroDecimals = string.Join("", decimalPart.Reverse().SkipWhile(c => c == '0').Reverse()); | |
| var addToMin = nonZeroDecimals.Length <= minDecimals ? minDecimals - nonZeroDecimals.Length : 0; | |
| var addToMax = maxDecimals - nonZeroDecimals.Length; // Already have a check | |
| sb.Append($@"|^{wholePart}{separator}{nonZeroDecimals}\d{{{addToMin},{addToMax}}}$"); | |
| } | |
| return sb.ToString()[1..sb.Length]; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The code generates regexp that maches any value in format [1-9]\d*.\d{minDecimals, maxDecimals} or 0.\d{minDecimals, maxDecimals} that is higher or equal (isInclusive = true) than "value"
Do not believe it works? Try for yourself!
https://regex101.com/
Example output:
For GenerateIsMoreThanRegexp(0):
^[1-9]\d{0,}\.\d{2,3}$|^0\.[1-9]\d{1,2}$|^0\.0[1-9]\d{0,1}$|^0\.00[1-9]\d{0,0}$|^0\.\d{2,3}$For GenerateIsMoreThanRegexp(5.2):
^[1-9]\d{1,}\.\d{2,3}$|^[6-9]\d{0,}\.\d{2,3}$|^5\.[3-9]\d{1,2}$|^5\.2[1-9]\d{0,1}$|^5\.20[1-9]\d{0,0}$|^5\.2\d{1,2}$For GenerateIsMoreThanRegexp(561340.62):
^[1-9]\d{6,}\.\d{2,3}$|^[6-9]\d{5,}\.\d{2,3}$|^5[7-9]\d{4,}\.\d{2,3}$|^56[2-9]\d{3,}\.\d{2,3}$|^561[4-9]\d{2,}\.\d{2,3}$|^5613[5-9]\d{1,}\.\d{2,3}$|^56134[1-9]\d{0,}\.\d{2,3}$|^561340\.[7-9]\d{1,2}$|^561340\.6[3-9]\d{0,1}$|^561340\.62[1-9]\d{0,0}$|^561340\.62\d{0,1}$