Eliminar caracteres no numéricos en una cadena


Respuestas:


234

Hay muchas formas, pero esto debería funcionar (aunque no sé cómo funciona con cadenas realmente grandes):

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

21
Probablemente debería utilizar en IsDigitlugar de IsNumber: "Este método [ IsNumber] determina si a Charpertenece a alguna categoría numérica Unicode. Además de incluir dígitos, los números incluyen caracteres, fracciones, subíndices, superíndices, números romanos, numeradores de moneda y números entre círculos. Este método contrasta con el IsDigitmétodo, que determina si a Chares un dígito de base 10 ". msdn.microsoft.com/en-us/library/yk2b3t2y.aspx
LukeH

2
@TrevorBrooks Supongamos que puede ampliar los términos:input.Where(c => char.IsDigit(c) || char.IsWhiteSpace(c))
Fredrik Mörk

6
Se puede simplificar aún más return new string(input.Where(char.IsDigit).ToArray());. Simplemente lo hago más legible
Zapnologica

2
Buena respuesta. Es posible que solo desee considerar cambiar el nombre de la función de 'GetNumbers' a 'GetDigits' también ... para dejar clara su intención.
JTech

2
También es un gran método de extensión.
Roberto Bonini

61

Se siente como una buena opción para una expresión regular.

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

"[^0-9]"puede ser reemplazado por @"\D"pero me gusta la legibilidad de [^0-9].


1
Estoy de acuerdo siempre que esté de acuerdo con la sobrecarga asociada con las expresiones regulares en .Net
FrankO

4
Por curiosidad, ¿cuál es el rendimiento general entre esta respuesta y la respuesta de Fredrik Mork?
Scuba Steve

Probablemente esto sea más lento, pero la única forma de saberlo es medir porque depende de cómo .NET implementa las expresiones regulares, cómo se compila la expresión Lambda y más.
Jonas Elfström

1
Esto es más flexible que usar IsDigit (), ya que puede agregar '.' caracteres a la expresión regular si desea permitir números con posiciones decimales.
Richard Moore

10
Hice una comparación simple de Regex versus LINQ en una cadena construida a partir de 100,000 GUID unidos (lo que resultó en una cadena de caracteres de 3,600,000). Regex fue consistentemente alrededor de medio segundo, mientras que LINQ estuvo consistentemente en el rango de 1/10 de segundo. Básicamente, LINQ fue 5 veces más rápido en promedio.
Chris Pratt

8

Un método de extensión será un mejor enfoque:

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

Prefiero if (text == null) return string.Empty;más text = text ?? string.Empty;. De esta forma no disminuimos el rendimiento.
Hooman

6

Use una expresión regular que solo capture 0-9 y descarte el resto. Sin embargo, una expresión regular es una operación que va a costar mucho la primera vez. O haz algo como esto:

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

Creo que algo así, aunque no lo he compilado ...

LINQ es, como dijo Fredrik, también una opción


4

Otra opción ...

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

2
¿Qué pasa con el negativo? (-) ¿No debería ser menos parte de esto?
Seabizkit

0

Bueno, ya sabes cuáles son los dígitos: 0123456789, ¿verdad? Atraviesa tu cadena carácter por carácter; si el carácter es un dígito, colóquelo al final de una cadena temporal, de lo contrario ignórelo. Puede haber otros métodos auxiliares disponibles para cadenas de C #, pero este es un enfoque genérico que funciona en todas partes.


0

Aquí está el código que usa expresiones 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()); 

¿Qué debo hacer para que Regex funcione y obtenga este error? El nombre 'Regex' no existe en el contexto actual
StevieB

utilizando System.Text.RegularExpressions;
dhirschl

0

La respuesta aceptada es excelente, sin embargo, no tiene en cuenta los valores NULL, por lo que es inutilizable en la mayoría de los escenarios.

Esto me llevó a usar estos métodos auxiliares en su lugar. El primero responde al OP, mientras que los otros pueden ser útiles para quienes quieran realizar lo contrario:

    /// <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 obtener información adicional, lea esta publicación en mi blog.


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.