5

I want to validate a string based on custom format: (_.__,_.__). This should be a decimal input followed by a comma followed by another decimal input, wrapped in a parentheses—e.g.(1.01,3.21). I want the string pattern to accept one and more entries—e.g.(1.01,3.21)(3.01,4.51)...(2.1,5.6). Is it possible to do that?

2
  • 1
    Please show what you have done so far, share your code. Regex.IsMatch can help.with a correct pattern Commented Apr 17, 2020 at 6:35
  • 1
    bool isValid = Regex.Replace(input, @"\(\d+\.\d+,\d+\.\d+\)", "").Length == 0; Commented Apr 17, 2020 at 7:52

3 Answers 3

3

One way to solve this is:

  • Use RegEx to return the matches of the (x,y) pattern.
  • Use the extension methods to extract the x and y.
  • Check whether the x and y are of decimal type using decimal.TryParse(..) method.
  • Check whether the input string contains something else other than the required pattern.
private bool IsValidInput(string input)
{
    var pattern = @"\((.*?)\s?,\s?(.*?)\)";
    var xpatt = @"\s+\(|\s+\)|\,\(|\)\,|\)\s+|\({2,}|\){2,}|^\)\(|\)\($";
    var q = Regex.Matches(input, pattern)
        .Cast<Match>()
        .SelectMany(x => x.Groups.Cast<Group>()
        .Skip(1))
        .Select(x => x.Value);

    return !Regex.IsMatch(input, xpatt)
        && q.Count() > 0 
        && input.Replace(" ","").Length 
        == (input.Count(x => x == '(' || x == ')' || x == ',') 
        + q.Sum(x => x.Length))
        && q.All(x => decimal.TryParse(x, out _));
}

So, the function returns:

(1.01, 3.21)(3.01, 4.51)(2.1, 5.6)     => true
(abc, 3.21)(3.01, 4.51)(2.1, 5.6)      => false
(3.21)(3.01, 4.51)(2.1, 5.6)           => false
1.01, 3.2 13.01, 4.51 2.1, 5.6         => false
1.01, 3.21)(3.01, 4.51)(2.1, 5.6)      => false
(1.01, 3.21)(3.01, 4.51)(2.1, 5.6      => false
1.01, 3.21)3.01, 4.51)2.1, 5.6)        => false
(1.01, 3.21)3.01, 4.51(2.1, 5.6)       => false
(1.01, 3.21)abc(3.01, 4.51)(2.1, 5.6)  => false
(1.01, 3.21)(3.01, 4.51)abc(2.1, 5.6)  => false
abc(1.01, 3.21)(3.01, 4.51)(2.1, 5.6)  => false
(1.01, 3.21)(3.01, 4.51)(2.1, 5.6)abc  => false
Sign up to request clarification or add additional context in comments.

Comments

1

You can either use

(?:\(\d+(?:\.\d+)?,\d+(?:\.\d+)?\))+

or with global flag

\(\d+(?:\.\d+)?,\d+(?:\.\d+)?\)

First solution will match your pattern 1 or more times and returns a single match. The second will match your pattern only once. However with global flag you will get all matches as separate results.

Explanation:

(?:                   //begin non-capturing group
  \(                  //match opening parentheses
    \d+               //match 1 or more numbers
    (?:\.\d+)?        //optionally match a dot followed by 1 or more numbers
    ,                 //match a comma
    \d+(?:\.\d+)?     //same pattern as before comma
  \)                  //match closing parentheses
)+                    //close non-capturing group, match the group 1 or more times

Comments

0

I think this should do the trick for your problem: ^(?:\(\d+(?:\.\d+)?,\d+(?:\.\d+)?\))+$ try it out Currently I made all capturing groups non capturing groups since I was not sure about any specific subgroups you wanted to capture.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.