Removendo caracteres não numéricos na string


Respostas:


234

Há muitas maneiras, mas isso deve servir (não sei como funciona com strings realmente grandes):

private static string GetNumbers(string input)
{
    return new string(input.Where(c => char.IsDigit(c)).ToArray());
}

21
Você provavelmente deve usar em IsDigitvez de IsNumber: "Este método [ IsNumber] determina se a Charpertence a qualquer categoria numérica Unicode. Além de incluir dígitos, os números incluem caracteres, frações, subscritos, sobrescritos, algarismos romanos, numeradores de moeda e números dentro de um círculo. Este método contrasta com o IsDigitmétodo, que determina se a Charé um dígito raiz de 10. " msdn.microsoft.com/en-us/library/yk2b3t2y.aspx
LukeH

2
@TrevorBrooks Suponha que você possa simplesmente expandir os termos:input.Where(c => char.IsDigit(c) || char.IsWhiteSpace(c))
Fredrik Mörk

6
Pode-se simplificar ainda mais para return new string(input.Where(char.IsDigit).ToArray());. Acabei de torná-lo mais legível
Zapnologica

2
Boa resposta. Talvez você queira apenas considerar renomear a função de 'GetNumbers' para 'GetDigits' também ... para deixar sua intenção clara.
JTech

2
Também é um ótimo método de extensão.
Roberto Bonini

61

Parece um bom ajuste para uma expressão regular.

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

"[^0-9]"pode ser substituído por, @"\D"mas gosto da legibilidade de [^0-9].


1
Eu concordaria, contanto que você esteja de acordo com a sobrecarga associada às expressões regulares em .Net
FrankO

4
Por curiosidade, qual é a sobrecarga de desempenho entre esta resposta e a resposta de Fredrik Mork?
Scuba Steve

Provavelmente é mais lento, mas a única maneira de saber é medir, porque depende de como o .NET implementa expressões regulares, como a expressão Lambda é compilada e muito mais.
Jonas Elfström

1
Isso é mais flexível do que usar IsDigit (), pois você pode adicionar '.' caracteres para o regex se você quiser permitir números com casas decimais.
Richard Moore

9
Fiz uma comparação simples de Regex vs. LINQ em uma string construída a partir de 100.000 GUIDs unidos (resultando em uma string de 3.600.000 caracteres). Regex estava consistentemente em torno de meio segundo, enquanto LINQ consistentemente estava na faixa de 1/10 de segundo. Basicamente, o LINQ foi 5 ou mais vezes mais rápido em média.
Chris Pratt

8

Um método de extensão será uma abordagem melhor:

public static string GetNumbers(this string text)
    {
        text = text ?? string.Empty;
        return new string(text.Where(p => char.IsDigit(p)).ToArray());
    }

Eu prefiro if (text == null) return string.Empty;terminar text = text ?? string.Empty;. Dessa forma, não diminuímos o desempenho.
Hooman

5

Use uma expressão regular que capture apenas 0-9 e jogue fora o resto. Uma expressão regular é uma operação que vai custar muito na primeira vez. Ou faça algo assim:

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();

Acho que algo assim, ainda não compilei ..

LINQ é, como disse Fredrik, também uma opção


4

Outra opção ...

private static string RemoveNonNumberDigitsAndCharacters(string text)
{
    var numericChars = "0123456789,.".ToCharArray();
    return new String(text.Where(c => numericChars.Any(n => n == c)).ToArray());
}

2
que tal negativo? (-) não deveria ser separado disso?
Seabizkit

0

Bem, você sabe quais são os dígitos: 0123456789, certo? Percorra sua string caractere por caractere; se o caractere for um dígito, coloque-o no final de uma string temporária, caso contrário, ignore. Pode haver outros métodos auxiliares disponíveis para strings C #, mas esta é uma abordagem genérica que funciona em qualquer lugar.


0

Aqui está o código usando expressões regulares:

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()); 

O que preciso fazer para obter o Regex funcionando ao obter este erro O nome 'Regex' não existe no contexto atual
StevieB de

using System.Text.RegularExpressions;
dhirschl de

0

A resposta aceita é ótima, porém não leva em consideração os valores NULL, tornando-o inutilizável na maioria dos cenários.

Isso me levou a usar esses métodos auxiliares. O primeiro responde ao OP, enquanto os demais podem ser úteis para quem deseja fazer o contrário:

    /// <summary>
    /// Strips out non-numeric characters in string, returning only digits
    /// ref.: /programming/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());
    }

Para obter informações adicionais, leia esta postagem no meu blog.


0
public static string RemoveNonNumeric(string value) => Regex.Replace(value, "[^0-9]", "");

-1
 var output = new string(input.Where(char.IsNumber).ToArray());
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.