patterncsharpMinor
Extracting a Decimal from a string
Viewed 0 times
fromdecimalstringextracting
Problem
I have the following method which extracts a decimal value from a string.
Is this the most effecticve way to do it?
using System;
using System.Linq;
using System.Text;
namespace Foo.Bar.Common.Converters
{
public static class DecimalConverter
{
public static Decimal ExtractDecimalFromString(string str)
{
var sb = new StringBuilder();
foreach (var c in str.Where(c => c == '.' || Char.IsDigit(c)))
{
sb.Append(c);
}
return Convert.ToDecimal(sb.ToString());
}
}
}Is this the most effecticve way to do it?
Solution
Regular expressions can be a good way of processing text input in situations like this. Your current process finds every digit in the input string, concatenates it together, and then parses the result.
I doubt that this is a good solution because it makes examples like: "There are 10 people arriving at 9pm" parse as
Even then, Regular expressions are probably a good solution:
In
Your code will still fail with an exception for input like "Hello", which has no digits, because the
Additionally, your code does not support negative input values. This can be a trick to accomplish, but, again, using regular expressions, it is not horrendous.
Finally, I feel you should only be parsing the first set of decimal-like digis in the input, not all of them.
Putting this all together, I would have:
And use the code:
I have put this, with some test cases, in this Ideone here;
I doubt that this is a good solution because it makes examples like: "There are 10 people arriving at 9pm" parse as
109. Is that what you want?Even then, Regular expressions are probably a good solution:
str = Regex.Replace(str, @"[.\D+]", "");In
str, replace all non-digits with "" (i.e. remove any non-digits).Your code will still fail with an exception for input like "Hello", which has no digits, because the
ToDecimal call will fail. Values with multiple . characters will also be interesting...Additionally, your code does not support negative input values. This can be a trick to accomplish, but, again, using regular expressions, it is not horrendous.
Finally, I feel you should only be parsing the first set of decimal-like digis in the input, not all of them.
Putting this all together, I would have:
- use regex
- parse the first set of digits
- accept negative inputs
And use the code:
public static Decimal ExtractDecimalFromString(string str)
{
Regex digits = new Regex(@"^\D*?((-?(\d+(\.\d+)?))|(-?\.\d+)).*");
Match mx = digits.Match(str);
//Console.WriteLine("Input {0} - Digits {1} {2}", str, mx.Success, mx.Groups);
return mx.Success ? Convert.ToDecimal(mx.Groups[1].Value) : 0;
}I have put this, with some test cases, in this Ideone here;
Code Snippets
str = Regex.Replace(str, @"[.\D+]", "");public static Decimal ExtractDecimalFromString(string str)
{
Regex digits = new Regex(@"^\D*?((-?(\d+(\.\d+)?))|(-?\.\d+)).*");
Match mx = digits.Match(str);
//Console.WriteLine("Input {0} - Digits {1} {2}", str, mx.Success, mx.Groups);
return mx.Success ? Convert.ToDecimal(mx.Groups[1].Value) : 0;
}Context
StackExchange Code Review Q#85053, answer score: 7
Revisions (0)
No revisions yet.