2013-07-03 39 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',你應該使用更多的迭代(儘管在這種情況下它可能會很好),並且你應該隔開測試調用來緩解後臺進程的週期性影響這可能會導致結果偏差。理想情況下,您還可以繪製分佈圖,以確保沒有異常值偏離平均值。 –