非数値を空の文字列に置き換えます


125

プロジェクトの要件をすばやく追加します。DBの電話番号を保持するフィールドは、10文字のみを許可するように設定されています。それで、「(913)-444-5555」または他の何かが渡された場合、許可する一連の文字を渡すことができるある種の特別な置換関数を介して文字列を実行する簡単な方法はありますか?

正規表現?

回答:


251

間違いなく正規表現:

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

またはクラス内で常に正規表現を再作成しないようにします。

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

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

実際の入力に応じて、先頭の1を取り除く(長距離の場合)か、xまたはXの後ろにあるもの(延長の場合)などを実行するための追加のロジックが必要になる場合があります。


それは最高です。これは数回しか使用されないため、クラスを作成する必要はありません。また、先頭の1までは、悪い考えではありません。しかし、少なくともこのプロジェクトでは、ケースバイケースでそれを処理したいと思います。改めて感謝します。もし私が再び賛成票を投じることができれば、そうします。
Matt Dawdy、2008年

1
私は誰かがこれの拡張メソッドバージョンを文字列クラスに投稿するのを待っています:)
Joel Coehoorn 2008年

@ジョエル以下の拡張メソッドバージョンを追加しました。コメントがマークダウンをサポートしていないと思います。
アーロン

13
メモ[^\d]は次のように簡略化できます\D
pswg

この回答(クラスの正規表現をキャッシュする)を以下の拡張メソッドと
組み合わせる

73

あなたは正規表現でそれを簡単に行うことができます:

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

2
素晴らしい答えであることに賛成ですが、ジョエルはあなたを打ち負かしました。でも答えてくれてありがとう-私は本当に複数の情報源からの確認を見たいです。
Matt Dawdy、2008年

@JoSmo公平に言うと、Joelはかなり簡単にワンライナーに変換できます。(しかし、私は:Dにも賛成しました)
Mage Xy

40

Regexを使用する必要はありません。

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

3
いい答え、RegularExpressions名前空間への参照を追加する理由
BTE

1
@BTEそれは単に利用している略記なのでsystem.linq;
Eric Milliot-Martinez

1
これは、正規表現ソリューションと比較してどの程度うまく機能しますか?
Shavais

2
@ Max-PCのLINQソリューションのベンチマークコードにテストを追加すると、StringBuilder:273ms、Regex:2096ms、LINQ:658msになります。StringBuilderよりも低速ですが、Regexよりも大幅に高速です。それが1,000,000の置換のベンチマークであることを考えると、ほとんどのシナリオでのStringBuilderソリューションとLINQソリューションの効果的な違いはおそらく無視できます。
クリスプラット

正規表現の@ChrisPratt、毎回新しい正規表現を作成しましたか、それとも既存の正規表現を再利用しましたか?これはパフォーマンスに大きな影響を与える可能性があります。
carlin.scott

23

これを行う拡張メソッドの方法を次に示します。

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

8

.NETのRegexメソッドを使用すると、次のように\ Dを使用して数値以外の数字を照合できるはずです。

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

5
これは正しくありません。正規表現で\をエスケープするには、@または "\\ D"が必要です。また、 ""の代わりにString.Emptyを使用する必要があります
Bryan

5

正規表現を使用しない拡張メソッドはどうでしょうか。

正規表現オプションのいずれかに固執する場合は、少なくともRegexOptions.Compiled静的変数で使用してください。

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

これは、メソッドグループに変換されたUsman Zafarの回答に基づいています。


4

最高のパフォーマンスとより少ないメモリ消費量のために、これを試してください:

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

私のコンピューターでの結果は:
Init ...
時間:307
時間:2178


ベンチマークを表示するための+1。興味深いのは、StringBuilderを使用したループがRegExよりも優れていることですが、RegExが何をすべきかを決定するために多くのルールをたどる必要がある場合は、おそらく理にかなっています。
Steve In CO

3

それを行うにはより効率的な方法があると確信していますが、おそらくこれを行うでしょう:

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

それが私の最初の本能であり、私がここで尋ねた理由でもありました。RegExは私にとってはるかに優れたソリューションのようです。しかし、答えてくれてありがとう!
Matt Dawdy 2008年

-1

これを試して

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();「System.Char []」を返します。私はあなたが意味したと思うがreturn new string(newPhone);、これはまた、>andの<代わりに>=andのために、0と9の数を除外している<=。ただし、その場合でも、newPhon配列が必要以上に長いため、stringには末尾のスペースが含まれます。
-juharr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.