在C#中格式化电话号码的最快方法是什么?

24

如何在C#中最快地使用美国电话格式[(XXX) XXX-XXXX]对字符串进行格式化?

我的源格式是一个字符串。


你的源格式是什么?另一个字符串吗?只有纯数字,没有其他字符吗? - bendewey
6个回答

56
String.Format("{0:(###) ###-#### x ###}", double.Parse("1234567890123"))

将得到(123) 456-7890 x 123


我很好奇,为什么要用 double.Parse 而不是 int.Parse?毕竟int更快。 - Ray
这个性能与子字符串方法相比如何?你知道 ##-##... 是不是只是使用子字符串类型技术进行解析? - bendewey
我刚刚使用int进行了测试,结果抛出了“值超出了Int32的范围”的异常。 - Michael Kniskern
也许 long 足够长了。我不太了解 .net 是否足够长度 :) decimal 肯定可以做到,但不确定是否仍然可以使用 ##。 - Johannes Schaub - litb
2
使用整数作为像电话号码这样的标识符是不好的实践,使用浮点类型是危险的:http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding - Paul
显示剩余3条评论

8
这假设你已经存储了带有适当位数的电话号码,例如:
string p = "8005551234";

string formatedPhoneNumber = string.Format("({0}) {1}-{2}", p.Substring(0, 3), p.Substring(3, 3), p.Substring(6, 4));

5

这将接受一个包含十个数字的字符串,格式可以是任何形式,例如"246 1377801"或者">> Phone:((246)) 13 - 778 - 01 <<",并将其格式化为"(246) 137-7801"

string formatted = Regex.Replace(
   phoneNumber,
   @"^\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*(\d)\D*$",
   "($1$2$3) $4$5$6-$7$8$9$10");

(如果字符串不恰好包含十个数字,则返回原始字符串。)

编辑:

构建字符串的快速方法是使用 StringBuilder。通过将容量设置为最终字符串的确切长度,您将使用相同的字符串缓冲区而无需重新分配,并且 ToString 方法将返回缓冲区本身作为最终字符串。

这假设源字符串仅包含十个数字:

string formatted =
   new StringBuilder(14)
   .Append('(')
   .Append(phoneNumber, 0, 3)
   .Append(") ")
   .Append(phoneNumber, 3, 3)
   .Append('-')
   .Append(phoneNumber, 6, 4)
   .ToString();

1
为什么不只使用一个正则表达式来去除非数字字符,再使用第二个正则表达式进行捕获和替换呢?虽然速度可能会慢一些,但代码会更加清晰。 - Sean Bright

4
我认为它应该是这样的:

var number = string.Format("({0}) {1}-{2}", oldNumber.Substring(0, 3), oldNumber.Substring(3, 3), oldNumber.Substring(6));

假设您将号码存储为“1234567890”,并且希望其显示为“(123) 456-7890”。


1

虽然不是最快的方法,但您可以使用扩展方法(请注意,参数必须清除任何先前的电话格式):

public static class StringFormatToWhatever
{
    public static string ToPhoneFormat(this string text)
    {        
        string rt = "";
        if (text.Length > 0)
        {            
            rt += '(';
            int n = 1;
            foreach (char c in text)
            {
                rt += c;
                if (n == 3) { rt += ") "; }
                else if (n == 6) { rt += "-"; }
                n++;
            }
        }
        return rt;
    }
}

然后,将其用作

myString.ToPhoneFormat();

如果您需要,可以根据自己的需求进行修改:

  • 包括电话分机号(x1234)
  • 清除方法内任何现有电话格式的参数
  • 使用破折号代替括号
  • 吃三明治...随你取名! :)

您还可以使用此方法来格式化每个用户输入的字符串。


-1
    private void txtPhone_Update()       
        {
            string phone = "";
            string phone1 = "";
            int index = 0;
            phone = txtPhone.Text;
            phone1 = "";

            for (index = 0; index < phone.Length; index++)
                if (char.IsDigit(phone[index]))
                { phone1 += phone[index]; }

                {
                    if (phone1[0] == '1') { phone1 = phone1.Remove(0, 1); }

                    {
                            string number = "";
                            number = string.Format("({0}) {1}-{2}", phone1.Substring(0, 3), phone1.Substring(3, 3), phone1[6..]);
                            phone1 = number;
                    }
                }
    }

我不知道你为什么写了 catch { }。你需要解释一下你的代码。 - Enigmativity
@Enigmativity 这段代码可以将电话号码格式化为(123) 456-7890。如果您想在catch中显示错误消息,可以这样做。不确定为什么要-1帖子。它可以在不使用正则表达式的情况下删除所有非数字字符。当然,如果try/catch让您感到不适,您可以将其删除。 - Rodney Livermore
除非你捕获了一个你有意义地处理的特定异常,否则仅包含try/catch是一种可怕的反模式。此外,你引入了某种UI层,当if (condition) { /* do something */ }更简单时,你有一个if (!condition) {} else { /* do something */ }。你还有phone1 = phone1 + phone[index],而phone1 += phone[index]会更清晰。为什么要涉及DataBindings?最后,你允许字符串超过10个字符,然后丢弃额外的字符。 - Enigmativity
这假设所需的输出是格式为(###) ###-####的10位数字电话号码,它将删除前导1和用于输入电话号码的任何额外的-或.。 - Rodney Livermore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接