用空字符串替换非数字


125

在我们的项目中快速添加需求。数据库中用于保存电话号码的字段设置为仅允许10个字符。因此,如果我通过了((913)-444-5555)或其他任何东西,是否有一种快速的方法可以通过某种特殊的替换函数来运行字符串,我可以将其传递给一组允许的字符?

正则表达式?

Answers:


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个而言,这不是一个坏主意。但是我认为我宁愿逐案处理,至少在这个项目中。再次感谢-如果我可以再次投票,我会的。
马特·道迪

1
我正在等待某人将其扩展方法版本发布为字符串类:)
Joel Coehoorn

@Joel我在下面添加了扩展方法版本。猜猜评论不支持降价。
亚伦

13
注意[^\d]可以简化为\D
pswg

将此答案(在该类中缓存正则表达式)与以下扩展方法结合起来:)
Vincent Vancalbergh 2015年

73

您可以使用正则表达式轻松完成此操作:

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

2
赞扬这是一个很好的答案,但乔尔击败了您。不过,感谢您的回答-我真的很想看到来自多个来源的确认。
马特·道迪

@JoSmo公平地说,Joel's可以很轻松地转换为单线。(但我也赞成:D)
法师Xy

40

您不需要使用正则表达式。

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

3
好的答案,为什么还要添加更多对RegularExpressions命名空间的引用
BTE 2014年

1
@BTE,因为它只是利用的system.linq;
简写形式

1
与Regex解决方案相比,此效果如何?
沙威

2
在LINQ解决方案的@ Max-PC基准代码中添加测试会导致-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, "");
    }
}

我的计算机中的结果是:
初始化...
时间: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对我来说似乎是一个更好的解决方案。但是,谢谢您的回答!
马特·道迪

-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);,但是,这也被过滤掉的数字0和9由于><而不是>=<=。但是即使那样,字符串也将具有尾随空格,因为newPhon数组的长度超过了所需的长度。
juharr
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.