[C#][Winform]GetWords小程式

  • 9939
  • 0
  • C#
  • 2009-10-14

摘要:[C#][Winform]GetWords小程式

最近寫了一個支援LearningEnglish的小程式(這篇),其主要的程式碼如下:

List<string> lstSource = new List<string>();
01 public void Convert()
02 {
03     //取得輸入
04     string[] arySource = (!String.IsNullOrEmpty(txtSource.Text.Trim())) ? txtSource.Lines : null;
05
06     if (arySource != null)
07     {
08         for (int i = 0; i < arySource.Length; i++)
09         {
10             //開始切字
11             ParseString(arySource[i]);
12         }

13         lstSource.TrimExcess();
14         //輸出結果
15         txtDestination.Lines = lstSource.ToArray();
16     }

17 }

18
19 public void ParseString(string data)
20 {
21     foreach (Match match in Regex.Matches(data, @"[a-zA-Z]+"))
22     {
23         if (match.Value.Length > 1)
24             lstSource.Add(match.Value.ToLower());
25     }

26     lstSource.Sort();
27     RemoveDuplicate();
28 }

29
30 public void RemoveDuplicate()
31 {
32     int i = 0;
33     while (i < lstSource.Count - 1)
34     {
35         if (lstSource[i] == lstSource[i + 1])
36             lstSource.Remove(lstSource[i + 1]);
37         else
38             i++;
39     }

40 }

這裡會轉成List<String>的原因主要是想利用他的Sort()來排序(懶得自己寫),不過它的效率似乎不是很理想,平均是O(n log n),worst case是O(n2) 

總覺得程式碼可以再漂亮一些、效能可以再好些,因此開放讓大家來找碴...
 

10/10/2009 更新:

根據網友larrynung提供的方法,使用List<T>.Contains()的方式可以免除呼叫副程式RemoveDuplicate(),測試結果發現速度稍有提昇:

去NY Times網站copy幾篇文章當作測試來源,先用原始的程式碼測試一遍,關掉程式;用新的程式碼測試一遍,關掉程式。以上方式測試兩次後的結果如下

 時間 (ms)記憶體用量 (MB)
舊法:第一次683125
新法:第一次661825
舊法:第二次683325
新法:第一次658025

 

 

 

 

 

 

 

 

可以發現新法的效能的確稍有提昇,larrynung

還有人有更好的想法嗎?

 

10/11/2009 更新:

larrynung又點出兩個盲點:Sort()應該放在副程式的外面 & 正規表示式可以一次全部批配。

所以我先把Sort()移出後得到下面結果

 時間 (ms)
第一次127
第二次127

 

 

 

可見這個Sort 擺錯地方影響有多大

之後把逐行批配改成一次全部批配得到如下結果

 時間 (ms)
第一次123
第二次121

 

 

 

還可以再次壓榨出效能

最後的code變得非常簡單,也不用再呼叫一些副程式了,如下:

public void Convert()
{
    foreach (Match match in Regex.Matches(txtSource.Text, @"[a-zA-Z]+"))
    {
        if (match.Value.Length > 2 && !lstSource.Contains(match.Value.ToLower()))
            lstSource.Add(match.Value.ToLower());
    }

    lstSource.TrimExcess();
    lstSource.Sort();
    txtDestination.Lines = lstSource.ToArray();
}

 經過這次的討論發現 細心 & 經驗 是這次程式效能校調的關鍵, 要再次給代表大家給提出意見的larrynung一個大拇指

 

參考:

1. [C#]以列為單位讀取MultiLine TextBox的內容

2. MSDN List<T>.Sort Method

3. MSDN List<T>.Contains() Method