2008-11-04 13 views
101

Requisito de complemento rápido en nuestro proyecto. Un campo en nuestro DB para mantener un número de teléfono está configurado para permitir solo 10 caracteres. Entonces, si me pasan "(913) -444-5555" o cualquier otra cosa, ¿hay una forma rápida de ejecutar una cadena a través de algún tipo de función de reemplazo especial que pueda pasarle un conjunto de caracteres para permitir?Reemplazar no numérico con cadena vacía

Regex?

Respuesta

206

Definitivamente expresiones regulares:

string CleanPhone(string phone) 
{ 
    Regex digitsOnly = new Regex(@"[^\d]"); 
    return digitsOnly.Replace(phone, ""); 
} 

o dentro de una clase para evitar la re-creación de la expresión regular todo el tiempo:

private static Regex digitsOnly = new Regex(@"[^\d]"); 

public static string CleanPhone(string phone) 
{ 
    return digitsOnly.Replace(phone, ""); 
} 

Dependiendo de sus entradas en el mundo real, es posible que desee algo de lógica adicional para hacer cosas como quitar los primeros 1 (para larga distancia) o cualquier cosa detrás de una x o X (para extensiones).

+0

Eso es perfecto. Esto solo se usa un par de veces, por lo que no es necesario crear una clase, y en cuanto a la 1 principal, no es una mala idea. Pero creo que preferiría manejar eso caso por caso, al menos en este proyecto. Gracias de nuevo. Si pudiera volver a votar nuevamente, lo haría. –

+1

Estoy esperando que alguien publique una versión de este método de extensión para la clase de cadena :) –

+0

@Joel Agregué la versión del método de extensión a continuación. Supongo que los comentarios no son compatibles con el descuento. – Aaron

3

Estoy seguro de que hay una manera más eficiente de hacerlo, pero probablemente ello:

string getTenDigitNumber(string input) 
{  
    StringBuilder sb = new StringBuilder(); 
    for(int i - 0; i < input.Length; i++) 
    { 
     int junk; 
     if(int.TryParse(input[i], ref junk)) 
      sb.Append(input[i]); 
    } 
    return sb.ToString(); 
} 
+0

Ese fue mi primer instinto, y también fue la razón por la que pregunté aquí. RegEx parece una solución mucho mejor para mí. ¡Pero gracias por la respuesta! –

65

Puede hacerlo fácilmente con expresiones regulares:

string subject = "(913)-444-5555"; 
string result = Regex.Replace(subject, "[^0-9]", ""); // result = "9134445555" 
+2

Upvoted por ser una gran respuesta, pero Joel te ganó. Sin embargo, gracias por la respuesta: realmente me gusta ver la confirmación de varias fuentes. –

+1

votada porque tu respuesta es de una sola línea. –

+0

@JoSmo Para ser justos, Joel's se puede convertir en un trazador de líneas bastante trivial. (Pero también volví a subir: D) –

8

Utilizando los métodos de expresiones regulares en .NET que debe ser capaz de igualar cualquier dígito no numérico usando \ D, así:

phoneNumber = Regex.Replace(phoneNumber, "\D", ""); 
+4

Esto no está del todo bien. Necesita un @ o "\\ D" para escapar de la \ en la expresión regular. Además, debe usar String.Empty en lugar de "" – Bryan

-1

probar esto

public static string cleanPhone(string inVal) 
     { 
      char[] newPhon = new char[inVal.Length]; 
      int i = 0; 
      foreach (char c in inVal) 
       if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0) 
        newPhon[i++] = c; 
      return newPhon.ToString(); 
     } 
+0

'return newPhone.ToString();' devolverá "System.Char []". Creo que quisiste decir 'return new string (newPhone);', Pero esto también está filtrando los números 0 y 9 debido a '>' y '<' en lugar de '> =' y '<='. Pero incluso entonces, la cadena tendrá espacios finales porque la matriz 'newPhon' es más larga de lo que necesita ser. – juharr

21

Aquí está el método de extensión de hacerlo.

public static class Extensions 
{ 
    public static string ToDigitsOnly(this string input) 
    { 
     Regex digitsOnly = new Regex(@"[^\d]"); 
     return digitsOnly.Replace(input, ""); 
    } 
} 
31

No necesita utilizar Regex.

phone = new String(phone.Where(c => char.IsDigit(c)).ToArray()) 
+3

Respuesta agradable, ¿por qué agregar más referencia al espacio de nombres RegularExpressions – BTE

+0

@BTE porque es una abreviatura que simplemente está utilizando 'system.linq;' –

+1

¿Qué tan bien funciona esto en comparación con la solución Regex? – Shavais

4

¿Qué tal un método de extensión que no utiliza expresiones regulares?

Si se atiene a una de las opciones de Regex, al menos use RegexOptions.Compiled en la variable estática.

public static string ToDigitsOnly(this string input) 
{ 
    return new String(input.Where(char.IsDigit).ToArray()); 
} 

Esto se basa en la respuesta de Usman Zafar convertido a un grupo de métodos.

4

para el mejor rendimiento y menor consumo de memoria, intente esto:

using System; 
using System.Diagnostics; 
using System.Text; 
using System.Text.RegularExpressions; 

public class Program 
{ 
    private static Regex digitsOnly = new Regex(@"[^\d]"); 

    public static void Main() 
    { 
     Console.WriteLine("Init..."); 

     string phone = "001-12-34-56-78-90"; 

     var sw = new Stopwatch(); 
     sw.Start(); 
     for (int i = 0; i < 1000000; i++) 
     { 
      DigitsOnly(phone); 
     } 
     sw.Stop(); 
     Console.WriteLine("Time: " + sw.ElapsedMilliseconds); 

     var sw2 = new Stopwatch(); 
     sw2.Start(); 
     for (int i = 0; i < 1000000; i++) 
     { 
      DigitsOnlyRegex(phone); 
     } 
     sw2.Stop(); 
     Console.WriteLine("Time: " + sw2.ElapsedMilliseconds); 

     Console.ReadLine(); 
    } 

    public static string DigitsOnly(string phone, string replace = null) 
    { 
     if (replace == null) replace = ""; 
     if (phone == null) return null; 
     var result = new StringBuilder(phone.Length); 
     foreach (char c in phone) 
      if (c >= '0' && c <= '9') 
       result.Append(c); 
      else 
      { 
       result.Append(replace); 
      } 
     return result.ToString(); 
    } 

    public static string DigitsOnlyRegex(string phone) 
    { 
     return digitsOnly.Replace(phone, ""); 
    } 
} 

El resultado en mi equipo es:
Init ...
Tiempo: 307
Tiempo: 2178

+0

+1 para mostrar puntos de referencia. Es interesante que el ciclo con StringBuilder supere a RegEx, aunque creo que tiene sentido cuando RegEx probablemente tenga que pasar por muchas reglas para decidir qué hacer. –

Cuestiones relacionadas