【问题标题】:C# Regular Expression filtering characters [closed]C#正则表达式过滤字符
【发布时间】:2013-09-23 21:33:12
【问题描述】:

我在 C# 中有一个字符串,我想过滤掉(丢弃)除数字以外的所有字符,即 0 到 9。例如,如果我有一个像 "5435%$% r3443_+_+** 这样的字符串╥╡←",那么输出应该是54353443。如何使用正则表达式或C#中的其他东西来完成?

谢谢

【问题讨论】:

  • Regex for numbers only的可能重复
  • 不是真正的重复。另一个问题是关于匹配只包含数字的字符串。
  • @user1 - 这不是一个重复的问题,可能是“相似的”。

标签: c# regex string filtering


【解决方案1】:

CODE:

using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Diagnostics;

public class Foo
{
    public static void Main()
    {
        string s = string.Empty;
        TimeSpan e;
        var sw = new Stopwatch();

        //REGEX        
        sw.Start();
        for(var i = 0; i < 10000; i++)
        {
            s = "123213!¤%//)54!!#¤!#%13425";
            s = Regex.Replace(s, @"\D", "");
        }
        sw.Stop();
        e = sw.Elapsed;

        Console.WriteLine(s);
        Console.WriteLine(e);

        sw.Reset();

        //NONE REGEX        
        sw.Start();
        for(var i = 0; i < 10000; i++)
        {
            s = "123213!¤%//)54!!#¤!#%13425";
            s = new string(s.Where(c => char.IsDigit(c)).ToArray());
        }
        sw.Stop();
        e = sw.Elapsed;

        Console.WriteLine(s);
        Console.WriteLine(e);
    }
}

OUTPUT:

1232135413425
00:00:00.0564964
1232135413425
00:00:00.0107598

结论:这显然有利于解决此问题的无正则表达式方法。

【讨论】:

    【解决方案2】:

    下面是一些没有正则表达式的例子:

    var str = "5435%$% r3443_+_+**╥╡←";
    var result = new string(str.Where(o => char.IsDigit(o)).ToArray());
    //Or you can make code above slightly more compact, using following syntax:
    var result = new string(str.Where(char.IsDigit).ToArray());
    

    从字符串中选择所有内容,即数字字符,并根据选择创建新字符串。

    谈到速度。

    var sw = new Stopwatch();
    var str = "5435%$% r3443_+_+**╥╡←";
    sw.Start();
    for (int i = 0; i < 100000; i++)
    {       
        var result = new string(str.Where(o => char.IsDigit(o)).ToArray());
    }
    sw.Stop();
    
    Console.WriteLine(sw.ElapsedMilliseconds); // Takes nearly 107 ms 
    
    sw.Reset();
    sw.Start();
    for (int i = 0; i < 100000; i++)
    {
        var s = Regex.Replace(str, @"\D", "");
    }
    sw.Stop();
    
    Console.WriteLine(sw.ElapsedMilliseconds); //Takes up to 600 ms
    
    
    sw.Reset();
    sw.Start();
    for (int i = 0; i < 100000; i++)
    {
        var newstr = String.Join("", str.Where(c => Char.IsDigit(c)));
    }
    sw.Stop();
    
    Console.WriteLine(sw.ElapsedMilliseconds); //Takes up to 109 ms
    

    因此,正则表达式的实现速度可以预见地很慢。加入和新字符串给出了非常相似的结果,也可能非常取决于用例。没有使用手动字符串循环测试实现,我相信它可能会给出最好的结果。

    更新。 还有正则表达式的 RegexOptions.Compiled 选项,示例中的用法是有意的。但是为了测试的清晰,可以说,编译的正则表达式在上面的示例中提供了近 150 毫秒的性能提升,这仍然很慢(比其他的慢 4 倍)。

    【讨论】:

      【解决方案3】:

      你不需要正则表达式

       var newstr = String.Join("", str.Where(c => Char.IsDigit(c)));
      

      【讨论】:

        【解决方案4】:

        你试过什么?

        static Regex rxNonDigits = new Regex( @"[^\d]+");
        public static string StripNonDigits( string s )
        {
          return rxNonDigits.Replace(s,"") ;
        }
        

        或者可能更有效

        public static string StripNonDigits( string s )
        {
          StringBuilder sb = new StrigBuilder(s.Length) ;
          foreach ( char c in s )
          {
            if ( !char.IsDigit(c) ) continue ;
            sb.Append(c) ;
          }
          return sb.ToString() ;
        }
        

        或等效的单线:

        public static string StripNonDigits( string s )
        {
          return new StringBuilder(s.Length)
                 .Append( s.Where(char.IsDigit).ToArray() )
                 .ToString()
                 ;
        }
        

        或者,如果您不关心其他文化的数字而只关心 ASCII 十进制数字,您可以节省 [也许] 昂贵的查找并进行两次比较:

        public static string StripNonDigits( string s )
        {
          return new StringBuilder(s.Length)
                 .Append( s.Where( c => c >= '0' && c <= '9' ).ToArray() )
                 .ToString()
                 ;
        }
        

        应该注意的是,LINQ 解决方案几乎肯定需要构造一个中间数组(使用 StringBuilder 不需要这样做。您也可以使用 LINQ 聚合:

        s.Where( char.IsDigit ).Aggregate(new StringBuilder(s.Length), (sb,c) => sb.Append(c) ).ToString()
        

        有不止一种方法可以做到!

        【讨论】:

          【解决方案5】:

          您可以简单地执行以下操作,字符类 [ ] 内的插入符号 (^) 是否定运算符。

          var pattern = @"[^0-9]+";
          var replaced = Regex.Replace("5435%$% r3443_+_+**╥╡←", pattern, "");
          

          输出:

          54353443
          

          【讨论】:

            【解决方案6】:

            ^ 会从匹配项中排除一个表达式。将其与匹配数字 0-9 的 \d 一起使用,并将其替换为空。

            var cleanString = Regex.Replace("123abc,.é", "^\d", "");
            

            【讨论】:

              猜你喜欢
              • 2012-10-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-09-12
              • 2023-03-29
              相关资源
              最近更新 更多