摘要:[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
}

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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) | |
舊法:第一次 | 6831 | 25 |
新法:第一次 | 6618 | 25 |
舊法:第二次 | 6833 | 25 |
新法:第一次 | 6580 | 25 |
可以發現新法的效能的確稍有提昇,larrynung
還有人有更好的想法嗎?
10/11/2009 更新:
larrynung又點出兩個盲點:Sort()應該放在副程式的外面 & 正規表示式可以一次全部批配。
所以我先把Sort()移出後得到下面結果
時間 (ms) | |
第一次 | 127 |
第二次 | 127 |
可見這個Sort 擺錯地方影響有多大
之後把逐行批配改成一次全部批配得到如下結果
時間 (ms) | |
第一次 | 123 |
第二次 | 121 |
還可以再次壓榨出效能
最後的code變得非常簡單,也不用再呼叫一些副程式了,如下:











經過這次的討論發現 細心 & 經驗 是這次程式效能校調的關鍵, 要再次給代表大家給提出意見的larrynung一個大拇指
參考:
1. [C#]以列為單位讀取MultiLine TextBox的內容
3. MSDN List<T>.Contains() Method