How to allow only 2 digits and 1 digit after the comma (.)? - flutter

I have the problem that I can't get the proper RegExp together.
My Goal is to allow up to 3 digits before the comma, and ONLY IF there is a decimal, then 1 digit after the comma. Which RegExp or Regexes do I have to use for this behavior?
Wanted allowed outcomes: 000.0, 00.0, 0.0, 000, 00, 0
thats the current code, but the problem is that here also 4 digits can be placed without a decimal:
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'^\d{1,3}\.?\d{0,1}')),
],
I already scrolled through these but they are not working for me:
Javascript Regex to allow only 2 digit numbers and 3 digit numbers as comma separated
Javascript regex to match only up to 11 digits, one comma, and 2 digits after it
Jquery allow only float 2 digit before and after dot
Flutter - Regex in TextFormField
Allow only two decimal number in flutter input?

RegExp(r'^\d{0,3}(\.\d{1})?$')
try this regex
also I think by comma your mean decimal (.) and considering you want 3 digits before decimal and 1 decimal after decimal
TextFormField(
autoValidateMode: AutoValidateMode.always,
validator: (value) {
return RegExp(r'^\d{0,3}(\.\d{1})?$').hasMatch(value) ? null : 'Invalid value';
},
)

I'm not a regex expert, so I can only suggest you using this helper function:
bool match(String input) {
if (input.split('.').length == 1) {
// if there is no dot in the string
// returns true if the length is < 4
return (input.length < 4) ? true : false;
} else if (input.split('.').length > 1){
// if there is more than one dot in the string
return false;
} else {
// if there is a dot in the string
// returns true if there are < 4 digits before the dot and exactly 1 digit
// after the dot
return (input.split('.')[0].length < 4 && input.split('.')[1].length == 1)
? true
: false;
}
}

Input formatter is not the case here because it formats data visually and your desired formats includes each other. You should use TextFormField and validator property with #Andrej's validator or use RegExp.
TextFormField(
autoValidateMode: AutoValidateMode.always,
validator: (value) {
return RegEx(r'^\d{1,3}(\.\d)?$').hasMatch(value) ? null : 'Invalid value';
},
)
RegExp is working here.

Related

Regular expression to find 3 consecutive numbers in a string equal to or increasing by 1 in Swift

I am writing a code that takes a string and verifies it. First, we created a regular expression that has a string length of 5 or more and less than 24 and can use only upper and lower case letters and dashes, and first verified.
func iDValidator(_ id: String) -> Bool {
let lengthAndElementRegEx = "^\\w{5,23}[a-zA-Z0-9-]$"
let continuousRegEx = "I Need!!!"
let lengthAndElementValidate = NSPredicate(format:"SELF MATCHES %#", lengthAndElementRegEx)
guard lengthAndElementValidate.evaluate(with: id) == true else {
return false
}
let continuousValidate = NSPredicate(format:"SELF MATCHES %#", continuousRegEx)
guard continuousValidate.evaluate(with: id) == true else {
print("###false")
return false
}
return true
}
After that, I would like to verify that a number appears 3 times in a row or 3 consecutive numbers in a string such as "111", "222", "123", and "456". Do you have a simple regex? Help!
You can use something like this:
([0-9])\1{2}|(012|123|234|345|456|567|678|789)
Where:
([0-9]) - Group 1 capturing 1 digit
\1{2} - Captures 2 more occurrences (due to the limiting quantifier {2}) of the value captured in Group 1 (where \1 is a backreference to Group 1 value)
(012|123|234|345|456|567|678|789) - simply matches all possible number sequences
You can try it yourself: https://regex101.com/r/noBKsE/2
Source

Swift 5: String prefix with a maximum UTF-8 length

I have a string that can contain arbitrary Unicode characters and I want to get a prefix of that string whose UTF-8 encoded length is as close as possible to 32 bytes, while still being valid UTF-8 and without changing the characters' meaning (i.e. not cutting off an extended grapheme cluster).
Consider this CORRECT example:
let string = "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}\u{1F1EA}\u{1F1FA}"
print(string) // 🏴󠁧󠁒󠁳󠁣󠁴󠁿πŸ‡ͺπŸ‡Ί
print(string.count) // 2
print(string.utf8.count) // 36
let prefix = string.utf8Prefix(32) // <-- function I want to implement
print(prefix) // 🏴󠁧󠁒󠁳󠁣󠁴󠁿
print(prefix.count) // 1
print(prefix.utf8.count) // 28
print(string.hasPrefix(prefix)) // true
And this example of a WRONG implementation:
let string = "ar\u{1F3F4}\u{200D}\u{2620}\u{FE0F}\u{1F3F4}\u{200D}\u{2620}\u{FE0F}\u{1F3F4}\u{200D}\u{2620}\u{FE0F}"
print(string) // arπŸ΄β€β˜ οΈπŸ΄β€β˜ οΈπŸ΄β€β˜ οΈ
print(string.count) // 5
print(string.utf8.count) // 41
let prefix = string.wrongUTF8Prefix(32) // <-- wrong implementation
print(prefix) // arπŸ΄β€β˜ οΈπŸ΄β€β˜ οΈπŸ΄
print(prefix.count) // 5
print(prefix.utf8.count) // 32
print(string.hasPrefix(prefix)) // false
What's an elegant way to do this? (besides trial&error)
You've shown no attempt at a solution and SO doesn't normally write code for you. So instead here as some algorithm suggestions for you:
What's an elegant way to do this? (besides trial&error)
By what definition of elegant? (like beauty it depends on the eye of the beholder...)
Simple?
Start with String.makeIterator, write a while loop, append Characters to your prefix as long as the byte count ≀ 32.
It's a very simple loop, worse case is 32 iterations and 32 appends.
"Smart" Search Strategy?
You could implement a strategy based on the average byte length of each Character in the String and using String.Prefix(Int).
E.g. for your first example the character count is 2 and the byte count 36, giving an average of 18 bytes/character, 18 goes into 32 just once (we don't deal in fractional characters or bytes!) so start with Prefix(1), which has a byte count of 28 and leaves 1 character and 8 bytes – so the remainder has an average byte length of 8 and you are seeking at most 4 more bytes, 8 goes into 4 zero times and you are done.
The above example shows the case of extending (or not) your prefix guess. If your prefix guess is too long you can just start your algorithm from scratch using the prefix character & byte counts rather than the original string's.
If you have trouble implementing your algorithm ask a new question showing the code you've written, describe the issue, and someone will undoubtedly help you with the next step.
HTH
I discovered that String and String.UTF8View share the same indices, so I managed to create a very simple (and efficient?) solution, I think:
extension String {
func utf8Prefix(_ maxLength: Int) -> Substring {
if self.utf8.count <= maxLength {
return Substring(self)
}
var index = self.utf8.index(self.startIndex, offsetBy: maxLength+1)
self.formIndex(before: &index)
return self.prefix(upTo: index)
}
}
Explanation (assuming maxLength == 32 and startIndex == 0):
The first case (utf8.count <= maxLength) should be clear, that's where no work is needed.
For the second case we first get the utf8-index 33, which is either
A: the endIndex of the string (if it's exactly 33 bytes long),
B: an index at the start of a character (after 33 bytes of previous characters)
C: an index somewhere in the middle of a character (after <33 bytes of previous characters)
So if we now move our index back one character (with formIndex(before:)) this will jump to the first extended grapheme cluster boundary before index which in case A and B is one character before and in C the start of that character.
I any case, the utf8-index will now be guaranteed to be at most 32 and at an extended grapheme cluster boundary, so prefix(upTo: index) will safely create a prefix with length ≀32.
…but it's not perfect.
In theory this should also be always the optimal solution, i.e. the prefix's count is as close as possible to maxLength but sometimes when the string ends with an extended grapheme cluster consisting of more than one Unicode scalar, formIndex(before: &index) goes back one character too many than would be necessary, so the prefix ends up shorter. I'm not exactly sure why that's the case.
EDIT: A not as elegant but in exchange completely "correct" solution would be this (still only O(n)):
extension String {
func utf8Prefix(_ maxLength: Int) -> Substring {
if self.utf8.count <= maxLength {
return Substring(self)
}
let endIndex = self.utf8.index(self.startIndex, offsetBy: maxLength)
var index = self.startIndex
while index <= endIndex {
self.formIndex(after: &index)
}
self.formIndex(before: &index)
return self.prefix(upTo: index)
}
}
I like the first solution you came up with. I've found it works more correctly (and simpler) if you take out the formIndex:
extension String {
func utf8Prefix(_ maxLength: Int) -> Substring {
if self.utf8.count <= maxLength {
return Substring(self)
}
let index = self.utf8.index(self.startIndex, offsetBy: maxLength)
return self.prefix(upTo: index)
}
}
My solution looks like this:
extension String {
func prefix(maxUTF8Length: Int) -> String {
if self.utf8.count <= maxUTF8Length { return self }
var utf8EndIndex = self.utf8.index(self.utf8.startIndex, offsetBy: maxUTF8Length)
while utf8EndIndex > self.utf8.startIndex {
if let stringIndex = utf8EndIndex.samePosition(in: self) {
return String(self[..<stringIndex])
} else {
self.utf8.formIndex(before: &utf8EndIndex)
}
}
return ""
}
}
It takes the highest possible utf8 index, checks if it is a valid character index using the Index.samePosition(in:) method. If not, it reduces the utf8 index one by one until it finds a valid character index.
The advantage is that you could replace utf8 with utf16 and it would also work.

Number validation and formatting

I want to format, in real time, the number entered into a UITextField. Depending on the field, the number may be an integer or a double, may be positive or negative.
Integers are easy (see below).
Doubles should be displayed exactly as the user enters with three possible exceptions:
If the user begins with a decimal separator, or a negative sign followed by a decimal separator, insert a leading zero:
"." becomes "0."
"-." becomes "-0."
Remove any "excess" leading zeros if the user deletes a decimal point:
If the number is "0.00023" and the decimal point is deleted, the number should become "23".
Do not allow a leading zero if the next character is not a decimal separator:
"03" becomes "3".
Long story short, one and only one leading zero, no trailing zeros.
It seemed like the easiest idea was to convert the (already validated) string to a number then use format specifiers. I've scoured:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
and
http://www.cplusplus.com/reference/cstdio/printf/
and others but can't figure out how to format a double so that it does not add a decimal when there are no digits after it, or any trailing zeros. For example:
x = 23.0
print (String(format: "%f", x))
//output is 23.000000
//I want 23
x = 23.45
print (String(format: "%f", x))
//output is 23.450000
//I want 23.45
On How to create a string with format?, I found this gem:
var str = "\(INT_VALUE) , \(FLOAT_VALUE) , \(DOUBLE_VALUE), \(STRING_VALUE)"
print(str)
It works perfectly for integers (why I said integers are easy above), but for doubles it appends a ".0" onto the first character the user enters. (It does work perfectly in Playground, but not my program (why???).
Will I have to resort to counting the number of digits before and after the decimal separator and inserting them into a format specifier? (And if so, how do I count those? I know how to create the format specifier.) Or is there a really simple way or a quick fix to use that one-liner above?
Thanks!
Turned out to be simple without using NumberFormatter (which I'm not so sure would really have accomplished what I want without a LOT more work).
let decimalSeparator = NSLocale.current.decimalSeparator! as String
var tempStr: String = textField.text
var i: Int = tempStr.count
//remove leading zeros for positive numbers (integer or real)
if i > 1 {
while (tempStr[0] == "0" && tempStr[1] != decimalSeparator[0] ) {
tempStr.remove(at: tempStr.startIndex)
i = i - 1
if i < 2 {
break
}
}
}
//remove leading zeros for negative numbers (integer or real)
if i > 2 {
while (tempStr[0] == "-" && tempStr[1] == "0") && tempStr[2] != decimalSeparator[0] {
tempStr.remove(at: tempStr.index(tempStr.startIndex, offsetBy: 1))
i = i - 1
if i < 3 {
break
}
}
}
Using the following extension to subscript the string:
extension String {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
}

Return Last 4 Digits of Phone Number in Velocity

I need to return the last 4 digits of a Phone Number field (where the format isn't consistent) to display as a PIN.
Apologies for my grotesque attempt but what can I change below to display $PIN as the last 4 digits of the phone field?
#set ($PIN = ${lead.IR_Main_Phone__c}.substring(0,-4))
You should filter non-digit characters in lead.IR_Main_Phone__c var, then get last 4 digits.
Example:
String phoneno = "+1-(800)-555-2468";
$phoneno.replaceAll("\D", ""); //Removes non-digit characters
$PIN = $phoneno.substring(0,-4) //gives: 2468
Also, another way without substring:
String phoneno = "+1-(800)-555-2468";
$phoneno.replaceAll("\D", ""); //Removes non-digit characters
$phoneno.replaceAll("(?=\d{5})\d", ""); //removes all but last 4 digits
$PIN = $phoneno //gives: 2468
isn't velocity an animation library?
Just use regular javascript
var str = "123-4 5 6 7";
var numbersOnly = str.match(/\d+/g, str).join('');
console.log(numbersOnly.length); // outputs 7
console.log(numbersOnly.substr(numbersOnly.length-4)); //output "4567"
Edit: now uses regex to filter out non-numbers

how to avoid the automatic rounding of decimal value in extjs ?

how to avoid the automatic rounding of decimal value in Extensible java script? For example if i enter 2.003 it will rounded as 2 or some times if i enter 2.039 it is accepting as 2.0388888887 please help me out.
For numberfields you can use decimal precision config
The maximum precision to display after the decimal separator (defaults to 2)
Technically it is simply toFixed:
fixPrecision : function(value) {
var nan = isNaN(value);
if (!this.allowDecimals || this.decimalPrecision == -1 || nan || !value) {
return nan ? '' : value;
}
return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
},