Remplacer non numérique par une chaîne vide


125

Ajout rapide des exigences dans notre projet. Un champ dans notre base de données pour contenir un numéro de téléphone est configuré pour n'autoriser que 10 caractères. Donc, si je passe "(913) -444-5555" ou autre chose, y a-t-il un moyen rapide d'exécuter une chaîne à travers une sorte de fonction de remplacement spéciale que je peux lui transmettre un jeu de caractères?

Regex?

Réponses:


251

Certainement regex:

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

ou dans une classe pour éviter de recréer l'expression régulière tout le temps:

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

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

En fonction de vos entrées du monde réel, vous voudrez peut-être une logique supplémentaire pour faire des choses comme supprimer les 1 en tête (pour les longues distances) ou tout ce qui suit un x ou un X (pour les extensions).


C'est parfait. Ceci n'est utilisé que quelques fois, donc nous n'avons pas besoin de créer une classe, et en ce qui concerne le premier 1, ce n'est pas une mauvaise idée. Mais je pense que je préfère gérer cela au cas par cas, du moins dans ce projet. Merci encore - si je pouvais voter à nouveau, je le ferais.
Matt Dawdy

1
J'attends que quelqu'un publie une version de la méthode d'extension de ceci pour la classe string :)
Joel Coehoorn

@Joel J'ai ajouté la version de la méthode d'extension ci-dessous. Je suppose que les commentaires ne prennent pas en charge le démarquage.
Aaron

13
La note [^\d]peut être simplifiée à\D
pswg

Combiné cette réponse (mise en cache de l'expression régulière dans la classe) avec la méthode d'extension ci-dessous :)
Vincent Vancalbergh

73

Vous pouvez le faire facilement avec regex:

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

2
J'ai voté pour être une excellente réponse, mais Joel vous a battu. Merci pour la réponse cependant - j'aime vraiment voir la confirmation de plusieurs sources.
Matt Dawdy

@JoSmo Pour être honnête, Joel's peut être converti en une seule ligne assez trivialement. (Mais j'ai aussi voté pour: D)
Mage Xy

40

Vous n'avez pas besoin d'utiliser Regex.

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

3
Bonne réponse, pourquoi ajouter plus de référence à l'espace de noms RegularExpressions
BTE

1
@BTE parce que c'est une main courte qui utilise simplementsystem.linq;
Eric Milliot-Martinez

1
Dans quelle mesure cela fonctionne-t-il par rapport à la solution Regex?
Shavais

2
L'ajout d'un test au code de référence de @ Max-PC pour la solution LINQ se traduit par - StringBuilder: 273ms, Regex: 2096ms, LINQ: 658ms. Plus lent que StringBuilder mais toujours nettement plus rapide que Regex. Étant donné qu'il s'agit de comparer 1 000 000 de remplacements, la différence effective entre les solutions StringBuilder et LINQ pour la plupart des scénarios est probablement négligeable.
Chris Pratt

@ChrisPratt pour la regex, avez-vous créé une nouvelle regex à chaque fois, ou ré-utilisé une existante? Cela pourrait avoir un impact important sur les performances.
carlin.scott le

23

Voici la méthode d'extension pour le faire.

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

8

En utilisant les méthodes Regex dans .NET, vous devriez pouvoir faire correspondre n'importe quel chiffre non numérique en utilisant \ D, comme ceci:

phoneNumber  = Regex.Replace(phoneNumber, "\\D", String.Empty);

5
Ce n'est pas tout à fait vrai. Vous avez besoin d'un @ ou d'un "\\ D" pour échapper au \ dans l'expression régulière. Aussi, vous devriez utiliser String.Empty au lieu de ""
Bryan

5

Que diriez-vous d'une méthode d'extension qui n'utilise pas regex.

Si vous vous en tenez à l'une des options Regex, utilisez au moins RegexOptions.Compiledla variable statique.

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

Cela s'appuie sur la réponse d'Usman Zafar convertie en groupe de méthodes.


4

pour obtenir les meilleures performances et réduire la consommation de mémoire, essayez ceci:

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, "");
    }
}

Le résultat sur mon ordinateur est:
Init ...
Heure: 307
Heure: 2178


+1 pour afficher des repères. Il est intéressant de noter que la boucle avec StringBuilder surpasse RegEx, bien que je suppose que cela a du sens quand RegEx doit probablement parcourir de nombreuses règles pour décider quoi faire.
Steve In CO

3

Je suis sûr qu'il existe un moyen plus efficace de le faire, mais je le ferais probablement:

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

C'était mon premier instinct, et c'est aussi pourquoi j'ai demandé ici. RegEx me semble être une bien meilleure solution. Mais merci pour la réponse!
Matt Dawdy

-1

essaye ça

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

return newPhone.ToString();renverra "System.Char []". Je pense que vous vouliez dire return new string(newPhone);, mais c'est aussi filtrer les nombres 0 et 9 à cause de >et <au lieu de >=et <=. Mais même dans ce cas, la chaîne aura des espaces à la fin car le newPhontableau est plus long que nécessaire.
juharr
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.