# Parsing a string using a regex and doing a mathematical calculation if there is a match

This is my first time writing anything in C#/.NET. I have written a simple function that takes a string, splits it, compares each split value with a regex and if it matches it'll take the second part of the string, which is a double and rounds it and than replaces the old value in the string with the new rounded value. However I feel like this code could be much cleaner but since I have no experience I'm not sure how. I would appreciate any tips so I can improve my skills

public static void Main()
{
String pattern = "FL2 (77) Flashing,77,a=1.875,A=90.0,b=3.625,B=95.0,c=1.375,C=175.0,d=2.5,hem=0.5,16GA-AL,";
string[] fParams = pattern.Split(',');
Regex regex = new Regex("([a-zA-Z]=.*?)");

for (int i = 0; i < fParams.Length; i++)
{
if (regex.IsMatch(fParams[i]))
{
Console.WriteLine("true " + fParams[i]);
if (fParams[i].Any(char.IsUpper))
{
Console.WriteLine("upper case", fParams[i]);
string[] param = fParams[i].Split('=');
// Note in actual program I do more complex calculations
Double value = Math.Round(Convert.ToDouble(param[1]));
pattern = pattern.Replace(fParams[i], param[0]+"="+Convert.ToString(value));
}
else
{
Console.WriteLine("lower case", fParams[i]);
string[] param = fParams[i].Split('=');
// Note in actual program I do more complex calculations
Double value = Math.Round(Convert.ToDouble(param[1]) * 2) / 2;
pattern = pattern.Replace(fParams[i], param[0] + "=" + Convert.ToString(value));
}

}
}

//return pattern;
}


Here is the link to the fiddle

There is a wonderful overload of the Regex.Replace method that takes a MatchEvaluator delegate which does exactly what you need it to:

var pattern = "FL2 (77) Flashing,77,a=1.875,A=90.0,b=3.625,B=95.0,c=1.375,C=175.0,d=2.5,hem=0.5,16GA-AL,";
var regex = new Regex("(?<label>[a-zA-Z]+)=(?<value>[^,]+)", RegexOptions.ExplicitCapture);

var result = regex.Replace(pattern, m =>
{
// Edited - as Paparazzi noted in the comments, I missed
// the fact that the calculation was different for uppercase
// and lowercase...

var newValue = m.Groups["label"].Value.Any(char.IsUpper)
? Math.Round(Convert.ToDouble(m.Groups["value"].Value))
: Math.Round(Convert.ToDouble(m.Groups["value"].Value) * 2) / 2;

return \$"{m.Groups["label"].Value}={newValue}";
});


I've used a few things that might be new to you:

1. ExplicitCapture specifies that the only valid captures are explicitly named or numbered groups of the form (?…) See documentation
2. String interpolation - see documentation
3. var which is implicit typing

I appreciate that the Regex might be more complicated than you're comfortable with but it simply says that I'm looking for 2 groups seperated by an = sign. The label group and the value group. You can then access these by name in the match evaluator. The [^,]+ means match one or more of any character which is not a comma.

# Edit:

You don't actually need the ExplicitCapture option - sorry, I modified your Regex and the first iteration had an extra set of () around it. I'll leave it in the answer as it's something that's worth knowing about.

• Question uses different value. Not sure that is the same regex. Still good points in answer. – paparazzo Jan 4 '18 at 15:47
• @Paparazzi - I'm not sure what you mean by "Question uses different value". The question just rounds the numbers and replaces them in the input string which is what this code does too. Could you clarify what you mean please? – RobH Jan 4 '18 at 16:29
• The question has two different equations for value. – paparazzo Jan 4 '18 at 16:33
• Oh - I see. Thank you, I missed that entirely. – RobH Jan 4 '18 at 18:37