Extracting a Decimal from a string I have the following method which extracts a decimal value from a string.

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 =&gt; c == '.' || Char.IsDigit(c)))
            {
                sb.Append(c);
            }
            return Convert.ToDecimal(sb.ToString());
        }
    }
}


Is this the most effecticve way to do it?
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 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;