2013-07-03 114 views
3

这是代码:如何从字符串[]中删除没有字母字符?

StringBuilder sb = new StringBuilder(); 
Regex rgx = new Regex("[^a-zA-Z0-9 -]"); 

var words = Regex.Split(textBox1.Text, @"(?=(?<=[^\s])\s+\w)"); 
for (int i = 0; i < words.Length; i++) 
{ 
    words[i] = rgx.Replace(words[i], ""); 
} 

当IM做Regex.Split()的话还包含有字符的字符串中的〔实施例:

Daniel>

Hello:

\r\nNew

hello---------------------------

,我需要得到只有一行字没有所有的迹象

所以我试图用这个循环,但我最终在的话有很多有"" 的地方有的地方只有------------------------

我不能在代码中稍后将它用作字符串。

+0

你可以用正则表达式来做到这一点,例如'(\ w + | \ s +)'。这会给你所有的单词(没有数字)和一个或多个之间的空格。 – Automatico

+2

@ Cort3z'\ w'为您提供字母,数字和下划线(或更多用于Unicode)。如果你只想要字母 –

+0

@JoeEnos,那么你可能需要'[a-zA-Z]'这是真的,完全忘了。 – Automatico

回答

9

你不需要一个正则表达式来清除非字母。这将删除所有非Unicode字母。

public string RemoveNonUnicodeLetters(string input) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach(char c in input) 
    { 
     if(Char.IsLetter(c)) 
      sb.Append(c); 
    } 

    return sb.ToString(); 
} 

或者,如果你只想让拉丁字母,您可以使用此

public string RemoveNonLatinLetters(string input) 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach(char c in input) 
    { 
     if(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') 
      sb.Append(c); 
    } 

    return sb.ToString(); 
} 

基准VS正则表达式

public static string RemoveNonUnicodeLetters(string input) 
{ 
     StringBuilder sb = new StringBuilder(); 
     foreach (char c in input) 
     { 
      if (Char.IsLetter(c)) 
       sb.Append(c); 
     } 

      return sb.ToString(); 
} 



static readonly Regex nonUnicodeRx = new Regex("\\P{L}"); 

public static string RemoveNonUnicodeLetters2(string input) 
{ 
    return nonUnicodeRx.Replace(input, ""); 
} 


static void Main(string[] args) 
{ 

    Stopwatch sw = new Stopwatch(); 

    StringBuilder sb = new StringBuilder(); 


    //generate guids as input 
    for (int j = 0; j < 1000; j++) 
    { 
     sb.Append(Guid.NewGuid().ToString()); 
    } 

    string input = sb.ToString(); 

    sw.Start(); 

    for (int i = 0; i < 1000; i++) 
    { 
     RemoveNonUnicodeLetters(input); 
    } 

    sw.Stop(); 
    Console.WriteLine("SM: " + sw.ElapsedMilliseconds); 

    sw.Restart(); 
    for (int i = 0; i < 1000; i++) 
    { 
     RemoveNonUnicodeLetters2(input); 
    } 

    sw.Stop(); 
    Console.WriteLine("RX: " + sw.ElapsedMilliseconds); 


} 

输出(SM =字符串操作,RX =正则表达式)

SM: 581 
RX: 9882 

SM: 545 
RX: 9557 

SM: 664 
RX: 10196 
+0

您可能不需要*正则表达式,但是您不认为正则表达式单行程式比您的代码更优越吗? –

+0

不一定。这种方法是可重用的,也可以在一行中调用。也更容易维护恕我直言。 – keyboardP

+1

...比直接表达意图的正则表达式更容易维护?这听起来很可笑。这是正则表达式*用于*的东西。 –

3

keyboardP的解决方案很不错 - 考虑一下吧。但正如我在评论中所指出的那样,正则表达式实际上是这项工作的正确工具,你只是让它变得不必要的复杂。实际的解决方法是一个班轮:

var result = Regex.Replace(input, "\\P{L}", ""); 

\P{…} specifies a Unicode character class we do not want to match(的\p{…}相反)。 L字母的Unicode字符类。

当然是有意义的封装成一个方法这一点,因为keyboardP一样。为了避免重新编译一遍又一遍的正则表达式,你也应该考虑拉正则表达式创造出实际的代码(尽管这可能不会给对性能有很大的影响):

static readonly Regex nonUnicodeRx = new Regex("\\P{L}"); 

public static string RemoveNonUnicodeLetters(string input) { 
    return nonUnicodeRx.Replace(input, ""); 
} 
+3

我的一个或两个同事*可能会理解''\\ P {L}“'。我有大约35位同事。我必须承认,公司不会雇用顶尖人才,但是您可能会明白这在可维护性方面会做些什么。我使用正则表达式很多(特别是在*开发期间),但不能在重要的代码中容易地避免它们... –

+0

@owlstead因此,在它旁边放置注释。这不是使用正确的工具进行工作的有效理由。相反,你*学习*工具 - 或者,在你的情况下,教育同事。是的,正则表达式对于外行人来说是神秘的,但条件操作符也是如此,但你应该*使用这些习惯用法的压倒性共识。我甚至不确定评论是否可以走到这里 - 代码完全不言自明,因为存在适当的正则表达式文档。 –

+0

哇这是真棒解决方案 – MonsterMMORPG

1

为了帮助康拉德和keyboardP决心他们的差异,我使用他们的代码进行了基准测试。事实证明,keyboardP的代码比康拉德代码

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Text.RegularExpressions; 

    namespace ConsoleApplication1 
    { 
     class Program 
     { 
      static void Main(string[] args) 
      { 
       string input = "[email protected]#*advfk234098awfdasdfq9823fna943"; 
       DateTime start = DateTime.Now; 
       for (int i = 0; i < 100000; i++) 
       { 
        RemoveNonUnicodeLetters(input); 
       } 
       Console.WriteLine(DateTime.Now.Subtract(start).TotalSeconds); 
       start = DateTime.Now; 
       for (int i = 0; i < 100000; i++) 
       { 
        RemoveNonUnicodeLetters2(input); 
       } 
       Console.WriteLine(DateTime.Now.Subtract(start).TotalSeconds); 
      } 
      public static string RemoveNonUnicodeLetters(string input) 
      { 
       StringBuilder sb = new StringBuilder(); 
       foreach (char c in input) 
       { 
        if (Char.IsLetter(c)) 
         sb.Append(c); 
       } 

       return sb.ToString(); 
      } 
      public static string RemoveNonUnicodeLetters2(string input) 
      { 
       var result = Regex.Replace(input, "\\P{L}", ""); 
       return result; 
      } 
     } 
    } 

我快10倍

0.12 
1.2 

作为输出

UPDATE:

要看看它是否是正则表达式的编译是减缓Regex方法,我把正则表达式放在一个只构造一次的静态变量中。

  static Regex rex = new Regex("\\P{L}"); 
      public static string RemoveNonUnicodeLetters2(string input) 
      { 
       var result = rex.Replace(input,m => ""); 
       return result; 
      } 

但是这对运行时没有影响。

+0

感谢您的基准。我刚刚添加了更少的循环和更长的字符串输入,并将结果关联起来。 – keyboardP

+1

只是为了好玩,如果您使用'char []'而不是'StringBuilder'进行基准测试,那么您的结果甚至会达到10%左右。 (构建一个字符串大小的临时数组,循环遍历字符串,用临时数组填充临时数组,然后将临时数组复制到一个正确大小的新数组,并将其传递到'string'构造函数中)。 –

+0

对于更复杂的正则表达式,提取创建实际上会对运行时产生重大影响。我仍然对.NET的正则表达式实现感到非常失望。正则表达式应该非常快。 FWIW,你的基准测试代码不是很可靠,你应该使用'StopWatch',你应该使用更多的迭代(尽管在这种情况下它可能会很好),并且你应该隔开测试调用来缓解后台进程的周期性影响这可能会导致结果偏差。理想情况下,您还可以绘制分布图,以确保没有异常值偏离平均值。 –