176

I'm looking to strip out non-numeric characters in a string in ASP.NET C#, i.e. 40,595 p.a. would end up as 40595.

Thanks

jkoop
  • 113
  • 1
  • 7
StevieB
  • 6,263
  • 38
  • 108
  • 193
  • 3
    Here's your answer: http://stackoverflow.com/questions/262448/replace-non-numeric-with-empty-string –  Oct 20 '10 at 12:06

13 Answers13

341

There are many ways, but this should do (don't know how it performs with really large strings though):

private static string GetNumbers(string input)
{
    return new string(input.Where(c => char.IsDigit(c)).ToArray());
}
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • 26
    You should probably use `IsDigit` rather than `IsNumber`: *"This method [`IsNumber`] determines whether a `Char` is of any numeric Unicode category. In addition to including digits, numbers include characters, fractions, subscripts, superscripts, Roman numerals, currency numerators, and encircled numbers. This method contrasts with the `IsDigit` method, which determines whether a `Char` is a radix-10 digit."* http://msdn.microsoft.com/en-us/library/yk2b3t2y.aspx – LukeH Oct 20 '10 at 12:19
  • How can I preserve the spaces between numbers using this method? – TrevorBrooks Feb 19 '15 at 21:22
  • 2
    @TrevorBrooks Is suppose you can just expand the terms: `input.Where(c => char.IsDigit(c) || char.IsWhiteSpace(c))` – Fredrik Mörk Feb 23 '15 at 13:03
  • 9
    One can simplify it further to `return new string(input.Where(char.IsDigit).ToArray());` . I just makes it more readable – Zapnologica May 20 '15 at 08:06
  • 3
    Nice answer. Might just want to consider renaming the function from 'GetNumbers' to 'GetDigits' as well...to make its intention clear. – JTech Aug 24 '15 at 04:09
  • But passing "100.00" returns 10000 from the method. It just removed dot operator – Linoy Oct 25 '18 at 13:18
  • Wait. I upvoted, but why ToArray()? – Jimmy T. Jun 03 '22 at 13:20
  • 1
    @JimmyT. as far as I know, the string class does not have a constructor that takes an IEnumerable, so it must be made into an array. – Fredrik Mörk Jun 03 '22 at 21:39
  • forgive me, but what else do I need to use this function? .Where is always has the squiggly under line. I get the message about 'am I missing a using statement'. – Dave Hampel Apr 20 '23 at 02:15
  • 1
    @DaveHampel Yes, you need a `using System.Linq;` statement. – Fredrik Mörk Apr 20 '23 at 08:27
91

Feels like a good fit for a regular expression.

var s = "40,595 p.a.";
var stripped = Regex.Replace(s, "[^0-9]", "");

"[^0-9]" can be replaced by @"\D" but I like the readability of [^0-9].

Jonas Elfström
  • 30,834
  • 6
  • 70
  • 106
  • 1
    I would agree as long as you are okay with the overhead associated with regular expressions in .Net – FrankO Feb 29 '16 at 19:32
  • 6
    Out of curiosity, what's the performance overhead between this answer, and Fredrik Mork's answer? – Scuba Steve Oct 27 '16 at 18:40
  • This is probably slower but the only way to know is to measure because it depends on how .NET implements Regular Expressions, how the Lambda Expression is compiled, and more. – Jonas Elfström Oct 28 '16 at 07:58
  • 1
    This is more flexible than using IsDigit() as you can add '.' characters to the regex if you want to allow numbers with decimal places. – Richard Moore Feb 03 '17 at 15:34
  • 19
    I did a simple comparison of Regex vs. LINQ on a string constructed from 100,000 GUIDs joined together (resulting in a 3,600,000 character string). Regex was consistently around half a second, whereas LINQ consistently was in the 1/10 of a second range. Basically LINQ was 5 or more times faster on average. – Chris Pratt Mar 13 '18 at 13:29
  • @RichardMoore - the LINQ approach can also be easily extended. E.g. `...Where(c => char.IsDigit(c) || char=='.')...`. Granted the Regex is more compact in that case. – ToolmakerSteve May 26 '20 at 23:40
  • Perfect! Single line code is always most interesting :) – Chandraprakash Oct 07 '21 at 13:24
10

An extension method will be a better approach:

public static string GetNumbers(this string text)
    {
        text = text ?? string.Empty;
        return new string(text.Where(p => char.IsDigit(p)).ToArray());
    }
Sean Larkin
  • 6,290
  • 1
  • 28
  • 43
Ercan Ayan
  • 219
  • 3
  • 4
  • 1
    I prefer ```if (text == null) return string.Empty;``` over ```text = text ?? string.Empty;```. This way we don't decrease performance. – Hooman Limouee Jul 10 '19 at 15:21
9
public static string RemoveNonNumeric(string value) => Regex.Replace(value, "[^0-9]", "");
Patrick Cairns
  • 143
  • 1
  • 7
7

Another option ...

private static string RemoveNonNumberDigitsAndCharacters(string text)
{
    var numericChars = "0123456789,.".ToCharArray();
    return new String(text.Where(c => numericChars.Any(n => n == c)).ToArray());
}
Jay Byford-Rew
  • 5,736
  • 1
  • 35
  • 36
6

Use either a regular expression that's only capturing 0-9 and throws away the rest. A regular expression is an operation that's going to cost a lot the first time though. Or do something like this:

var sb = new StringBuilder();
var goodChars = "0123456789".ToCharArray();
var input = "40,595";
foreach(var c in input)
{
  if(goodChars.IndexOf(c) >= 0)
    sb.Append(c);
}
var output = sb.ToString();

Something like that I think, I haven't compiled though..

LINQ is, as Fredrik said, also an option

Onkelborg
  • 3,927
  • 1
  • 19
  • 22
3

As of C# 3.0, you should use method groups in lieu of lambda expressions where possible. This is because using method groups results in one less redirect, and is thus more efficient.

The currently accepted answer would thus become:

private static string GetNumbers(string input)
{
    return new string(input.Where(char.IsDigit).ToArray());
}
C Bergs
  • 71
  • 7
2
 var output = new string(input.Where(char.IsNumber).ToArray());
Emre
  • 144
  • 2
  • 17
0

Well, you know what the digits are: 0123456789, right? Traverse your string character-by-character; if the character is a digit tack it onto the end of a temp string, otherwise ignore. There may be other helper methods available for C# strings but this is a generic approach that works everywhere.

Tim
  • 5,371
  • 3
  • 32
  • 41
0

Here is the code using Regular Expressions:

string str = "40,595 p.a.";

StringBuilder convert = new StringBuilder();

string pattern = @"\d+";
Regex regex = new Regex(pattern);

MatchCollection matches = regex.Matches(str);

foreach (Match match in matches)
{
convert.Append(match.Groups[0].ToString());
}

int value = Convert.ToInt32(convert.ToString()); 
dhirschl
  • 2,088
  • 13
  • 18
0

The accepted answer is great, however it doesn't take NULL values into account, thus making it unusable in most scenarios.

This drove me into using these helper methods instead. The first one answers the OP, while the others may be useful for those who want to perform the opposite:

    /// <summary>
    /// Strips out non-numeric characters in string, returning only digits
    /// ref.: https://stackoverflow.com/questions/3977497/stripping-out-non-numeric-characters-in-string
    /// </summary>
    /// <param name="input">the input string</param>
    /// <param name="throwExceptionIfNull">if set to TRUE it will throw an exception if the input string is null, otherwise it will return null as well.</param>
    /// <returns>the input string numeric part: for example, if input is "XYZ1234A5U6" it will return "123456"</returns>
    public static string GetNumbers(string input, bool throwExceptionIfNull = false)
    {
        return (input == null && !throwExceptionIfNull) 
            ? input 
            : new string(input.Where(c => char.IsDigit(c)).ToArray());
    }

    /// <summary>
    /// Strips out numeric and special characters in string, returning only letters
    /// </summary>
    /// <param name="input">the input string</param>
    /// <param name="throwExceptionIfNull">if set to TRUE it will throw an exception if the input string is null, otherwise it will return null as well.</param>
    /// <returns>the letters contained within the input string: for example, if input is "XYZ1234A5U6~()" it will return "XYZAU"</returns>
    public static string GetLetters(string input, bool throwExceptionIfNull = false)
    {
        return (input == null && !throwExceptionIfNull) 
            ? input 
            : new string(input.Where(c => char.IsLetter(c)).ToArray());
    }

    /// <summary>
    /// Strips out any non-numeric/non-digit character in string, returning only letters and numbers
    /// </summary>
    /// <param name="input">the input string</param>
    /// <param name="throwExceptionIfNull">if set to TRUE it will throw an exception if the input string is null, otherwise it will return null as well.</param>
    /// <returns>the letters contained within the input string: for example, if input is "XYZ1234A5U6~()" it will return "XYZ1234A5U6"</returns>
    public static string GetLettersAndNumbers(string input, bool throwExceptionIfNull = false)
    {
        return (input == null && !throwExceptionIfNull) 
            ? input 
            : new string(input.Where(c => char.IsLetterOrDigit(c)).ToArray());
    }

For additional info, read this post on my blog.

Darkseal
  • 9,205
  • 8
  • 78
  • 111
0

If you're working in VB and ended up here, the ".Where" threw an error for me. Got this from here: https://forums.asp.net/t/1067058.aspx?Trimming+a+string+to+remove+special+non+numeric+characters

Function ParseDigits(ByVal inputString as String) As String
  Dim numberString As String = ""
  If inputString = Nothing Then Return numberString

  For Each c As Char In inputString.ToCharArray()
    If c.IsDigit Then
      numberString &= c
    End If
  Next c

  Return numberString
End Function
Tony L.
  • 17,638
  • 8
  • 69
  • 66
0

Strips out all non Numeric characters

Public Function OnlyNumeric(strIn As String) As String
      Try
            Return Regex.Replace(strIn, "[^0-9]", "")
      Catch
            Return String.Empty
      End Try
End Function
Leonardo Alves Machado
  • 2,747
  • 10
  • 38
  • 53
  • 1
    Welcome to the site. This is a valid answer in VB, but please note that the question is for C#. It would help if you [edit] your answer to add an explanation for your answer. For example, "Here is a VB translation of the answer from 2010." or something like that. – General Grievance May 01 '22 at 23:35