【问题标题】:Replace non-numeric with empty string用空字符串替换非数字
【发布时间】:2010-09-20 17:14:53
【问题描述】:

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

正则表达式?

【问题讨论】:

    标签: c# regex string phone-number


    【解决方案1】:

    绝对是正则表达式:

    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 而言,这不是一个坏主意。但我想我宁愿根据具体情况来处理,至少在这个项目中是这样。再次感谢 - 如果我能再次投票,我会的。
    • 我正在等待有人为字符串类发布此扩展方法版本:)
    • @Joel 我在下面添加了扩展方法版本。猜猜cmets不支持markdown。
    • 注意[^\d]可以简化为\D
    • 将此答案(在类中缓存正则表达式)与下面的扩展方法之一结合起来:)
    【解决方案2】:

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

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

    【讨论】:

    • 被赞成为一个很好的答案,但乔尔打败了你。不过感谢您的回答——我真的很想看到来自多个来源的确认。
    • @JoSmo 公平地说,Joel's 可以非常简单地转换为单线。 (但我也赞成:D)
    【解决方案3】:

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

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

    【讨论】:

    • 不错的答案,为什么要添加更多对正则表达式命名空间的引用
    • @BTE 因为它是一种简写方式,只是使用system.linq;
    • 与 Regex 解决方案相比,它的性能如何?
    • 将测试添加到@Max-PC 的 LINQ 解决方案的基准代码会导致 -- StringBuilder: 273ms, Regex: 2096ms, LINQ: 658ms。比 StringBuilder 慢,但仍然比 Regex 快得多。鉴于这是对 1,000,000 次替换进行基准测试,对于大多数场景,StringBuilder 和 LINQ 解决方案之间的有效差异可能可以忽略不计。
    • @ChrisPratt 对于正则表达式,您是每次都创建一个新的正则表达式,还是重复使用现有的正则表达式?这可能会对性能产生重大影响。
    【解决方案4】:

    这是扩展方法的做法。

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

    【讨论】:

      【解决方案5】:

      使用 .NET 中的 Regex 方法,您应该能够使用 \D 匹配任何非数字数字,如下所示:

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

      【讨论】:

      • 这不太对。您需要 @ 或 "\\D" 来转义正则表达式中的 \。此外,您应该使用 String.Empty 而不是 ""
      【解决方案6】:

      不使用正则表达式的扩展方法怎么样。

      如果您坚持使用其中一个正则表达式选项,至少在静态变量中使用 RegexOptions.Compiled

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

      这建立在 Usman Zafar 转换为方法组的答案之上。

      【讨论】:

        【解决方案7】:

        为了获得最佳性能和更低的内存消耗,试试这个:

        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 可能不得不通过大量规则来决定要做什么是有道理的。
        【解决方案8】:

        我确信有一种更有效的方法,但我可能会这样做:

        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 对我来说似乎是一个更好的解决方案。不过谢谢你的回答!
        【解决方案9】:

        试试这个

        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,因为&gt;&lt;而不是&gt;=&lt;=。但即便如此,字符串也会有尾随空格,因为 newPhon 数组比它需要的长。
        猜你喜欢
        • 2012-09-04
        • 2010-12-20
        • 2010-12-01
        • 2011-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-18
        • 2014-11-12
        相关资源
        最近更新 更多