从字符串中仅保留数字值?

29

我有一些像这样的字符串

string phoneNumber = "(914) 395-1430";

我想去掉括号和破折号,只保留数字值。

因此输出可能如下所示:

9143951430

我该如何获得所需的输出?


2
即使您没有正则表达式的经验,您至少应该进行一些研究。答案数量与问题难度成反比。 - Jerry
4
总有像你一样的人抱怨问题。这是一个问答网站,如果我知道答案就不会问了,谢谢! - meda
1
我并不是在抱怨,只是想让你知道已经有这种东西存在了。而且SO的政策之一就是将所有重复的问题重定向到一个主要问题上。重复的问题通常会被删除。 - Jerry
@SystemDown 我知道怎么做,但如果我不确定,我会问一下。你看,我最终使用了不需要正则表达式的答案。这是我完全不知道的东西。 - meda
5
为什么那个回答被关闭了?我从谷歌搜索“C#从字符串中提取数字”来到这里,而这个完全有效、简单且普适的问题却被关闭为“离题”。离题是指什么?编程主题?我认为这非常相关。什么鬼 Stack Overflow。 - v.oddou
显示剩余3条评论
6个回答

61

您可以执行以下任一操作:

  • 使用正则表达式。您可以使用具有以下负字符类的正则表达式,定义不希望出现的字符(除了十进制数字之外的字符):

    private static readonly Regex rxNonDigits = new Regex( @"[^\d]+");
    

    在这种情况下,您可以采取以下任一方法:

    // simply replace the offending substrings with an empty string
    private string CleanStringOfNonDigits_V1( string s )
    {
      if ( string.IsNullOrEmpty(s) ) return s ;
      string cleaned = rxNonDigits.Replace(s, "") ;
      return cleaned ;
    }
    
    // split the string into an array of good substrings
    // using the bad substrings as the delimiter. Then use
    // String.Join() to splice things back together.
    private string CleanStringOfNonDigits_V2( string s )
    {
      if (string.IsNullOrEmpty(s)) return s;
      string cleaned = String.Join( rxNonDigits.Split(s) );
      return cleaned ;
    }
    
  • 定义了你想要的内容的正字符集(十进制数字):

  • private static Regex rxDigits = new Regex( @"[\d]+") ;
    

    如果您遇到这种情况,可以像这样做:

    private string CleanStringOfNonDigits_V3( string s )
    {
      if ( string.IsNullOrEmpty(s) ) return s ;
      StringBuilder sb = new StringBuilder() ;
      for ( Match m = rxDigits.Match(s) ; m.Success ; m = m.NextMatch() )
      {
        sb.Append(m.Value) ;
      }
      string cleaned = sb.ToString() ;
      return cleaned ;
    }
    
  • 您不必使用正则表达式。

    • 您可以直接使用LINQ,因为字符串是IEnumerable<char>

  • private string CleanStringOfNonDigits_V4( string s )
    {
      if ( string.IsNullOrEmpty(s) ) return s;
      string cleaned = new string( s.Where( char.IsDigit ).ToArray() ) ;
      return cleaned;
    }
    
  • 如果您只涉及西方字母表,并且您将看到的唯一十进制数字是ASCII码,那么跳过char.IsDigit可能会稍微提高性能:

  • private string CleanStringOfNonDigits_V5( string s )
    {
      if (string.IsNullOrEmpty(s)) return s;
      string cleaned = new string(s.Where( c => c-'0' < 10 ).ToArray() ) ;
      return cleaned;
    }
    
  • 最后,您可以简单地迭代字符串,并丢弃您不想要的数字,例如:

  • private string CleanStringOfNonDigits_V6( string s )
    {
      if (string.IsNullOrEmpty(s)) return s;
      StringBuilder sb = new StringBuilder(s.Length) ;
      for (int i = 0; i < s.Length; ++i)
      {
        char c = s[i];
        if ( c < '0' ) continue ;
        if ( c > '9' ) continue ;
        sb.Append(s[i]);
      }
      string cleaned = sb.ToString();
      return cleaned;
    }
    
    这个:

    private string CleanStringOfNonDigits_V7(string s)
    {
      if (string.IsNullOrEmpty(s)) return s;
      StringBuilder sb = new StringBuilder(s);
      int j = 0 ;
      int i = 0 ;
      while ( i < sb.Length )
      {
        bool isDigit = char.IsDigit( sb[i] ) ;
        if ( isDigit )
        {
          sb[j++] = sb[i++];
        }
        else
        {
          ++i ;
        }
      }
      sb.Length = j;
      string cleaned = sb.ToString();
      return cleaned;
    }
    

    就清晰性和代码整洁度而言,版本1是您想要的。很难击败一行代码。

    如果性能很重要,我怀疑最后一个版本7是赢家。它创建了一个临时的StringBuilder(),并在StringBuilder的缓冲区内部原地进行转换。

    其他选项都会做更多的工作。


    9
    哇,你的回答非常详细,比我的问题多了很多内容,这让我有更多选择和理解。像你这样的用户使得SO成为一个伟大的社区。非常感谢!!! - meda

    35
    使用正则表达式
     string result = Regex.Replace(phoneNumber, @"[^\d]", "");
    

    1
    不错的一行代码。或者使用... @"[^\d]+" ...(在表达式中添加“+”)以便每次替换收集更多的字符。尚未测试这是否会产生速度差异。 - ToolmakerSteve

    13

    试试这样做

      return new String(input.Where(Char.IsDigit).ToArray());
    

    10
    string phoneNumber = "(914) 395-1430";
    var numbers = String.Join("", phoneNumber.Where(char.IsDigit));
    

    5
    他的意思是@gleng很重要。
    Regex rgx = new Regex(@"\D");
    str = rgx.Replace(str, "");
    

    @符号很重要! - Jerry
    谢谢两位。但是你们能不能帮我想起来为什么呢?我之前用过,但是忘记为什么了?因为它是用来表达文本的 :/ - Darka
    @符号将文本转换为原始文本,因此您无需转义反斜杠。否则,程序会尝试进行替换,最终只得到一个正则表达式 D - Jerry
    是的,有些东西需要记住。再次感谢。 - Darka

    2

    你可以使用 LINQ 方法替代正则表达式:

    phoneNumber = String.Concat(phoneNumber.Where(c => c >= '0' && c <= '9'));
    

    或者:

    phoneNumber = String.Concat(phoneNumber.Where(Char.IsDigit));
    

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