Individual Project_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > Individual Project

Individual Project

 2014/9/26 3:03:53  Word_frequency  程序员俱乐部  我要评论(0)
  • 摘要:作业说明详见:http://www.cnblogs.com/jiel/p/3978727.html一.预先准备和时间规划1.安装MicrosoftVisualStudioUltimate2012,之前安装过一次,预计2小时左右,但是安装过程中可以继续进行其它任务。2.阅读题目要求,理解要实现的功能,预计20min左右。3.根据题目,设计程序框架,预计10min左右。4.阅读相关文档,学习所需要的类的命名空间,属性和方法,预计1小时左右。5.初步完成程序编写,预计3小时左右。6.设计测试数据
  • 标签:project

作业说明详见:http://www.cnblogs.com/jiel/p/3978727.html

一.预先准备和时间规划

1.安装Microsoft Visual Studio Ultimate 2012,之前安装过一次,预计2小时左右,但是安装过程中可以继续进行其它任务。

2.阅读题目要求,理解要实现的功能,预计20min左右。

3.根据题目,设计程序框架,预计10min左右。

4.阅读相关文档,学习所需要的类的命名空间,属性和方法,预计1小时左右。

5.初步完成程序编写,预计3小时左右。

6.设计测试数据,对出现的Bug进行改进,预计2小时左右。

二.实际用时和具体过程

1.安装Microsoft Visual Studio Ultimate 2012,网址如下:

  http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=30678

网速较快用时1小时。

2.阅读题目要求,理解要实现的功能:实现一个文本词频统计器,可以实现统计单词数目,2联短语数目,3联短语数目。单词比较忽略大小写,输出时按照词频从大到小排序,相等时按字典序排序,用时15min。

3.根据题目,设计程序框架,完善代码:(用时大约4小时)

  (1)根据读入目录路径,获取目录子文件:

class="code_img_closed" src="/Upload/Images/2014092603/0015B68B3C38AA5B.gif" alt="" />
1 String[] files = Directory.GetFiles(path);
View Code

  (2)读取每个文件的内容:

 1 foreach (String i in files)
 2 {
 3     String extension = i.Substring(i.LastIndexOf(".")+1, i.Length - i.LastIndexOf(".")-1);
 4     if (!extension.Equals("txt") &&
 5         !extension.Equals("cpp") &&
 6         !extension.Equals("h") &&
 7         !extension.Equals("cs")) continue;//只处理特定格式的文件
 8     if (i.Equals(path+"\\"+"12061162.txt")) continue;
 9     String[] text = rgxwords.Split(File.ReadAllText(i));
10 }
View Code

  (3)对于获取的文本信息整理:先将文本拆分成若干行或者句子,设定三个Regex类,分别匹配单个单词,2两个由单个空格隔开的单词,3个由单个单词隔开的单词。调用Regex.Match()方法和Regex.NextMatch方法匹配所有可匹配项:

    数据存放数组定义如下:

adb7018" class="code_img_closed" src="/Upload/Images/2014092603/0015B68B3C38AA5B.gif" alt="" />
1 ArrayList data = new ArrayList();//当前小说的单词数据
2 ArrayList word_word = new ArrayList();//e2模式短语的数据
3 ArrayList word_word_word = new ArrayList();//e3模式短语的数据
View Code

    模板定义如下:

1 Regex rgxwords = new Regex("[\n\r,.\\(\\)\\{\\}\\{\\]:\"!;]+");//将文本拆分成一句或一行一个
2 Regex regword1 = new Regex("[a-zA-Z]{3}[0-9a-zA-Z]*");//Simple mode的模式
3 Regex regword2 = new Regex("[a-zA-Z]{3}[0-9a-zA-Z]* [a-zA-Z]{3}[0-9a-zA-Z]*");//Extended mode2的模式
4 Regex regword3 = new Regex("[a-zA-Z]{3}[0-9a-zA-Z]* [a-zA-Z]{3}[0-9a-zA-Z]* [a-zA-Z]{3}[0-9a-zA-Z]*");//Extended mode3的模式
View Code

    具体过程如下:

 1 Match match = regword1.Match(text[j], 0);
 2 while (match.Success)
 3 {
 4     data.Add(new Data(match.Value, 1));//simple mode的数据更新
 5     match = match.NextMatch();
 6 }
 7 Match match2 = regword2.Match(text[j], 0);
 8  Match match1 = regword1.Match(text[j],match2.Index);
 9 while (match2.Success)
10 {
11     word_word.Add(new Data(match2.Value, 1));
12     match2 = regword2.Match(text[j], match1.Index+1);
13     match1 = match1.NextMatch();
14 }//extend mode2的数据更新
15 match2 = regword3.Match(text[j], 0);
16 match1 = regword1.Match(text[j],match2.Index);
17 while (match2.Success)
18 {
19     word_word_word.Add(new Data(match2.Value, 1));
20     match2 = regword3.Match(text[j], match1.Index + 1);
21     match1 = match1.NextMatch();
22 }//extend mode3的数据更新   
View Code

   (4)对于存取数据的ArrayList类整理排序:主要运用ArrayList.sort(IComparer)方法,需要自己实现IComparer接口

 1         class myReverserClass1 : IComparer
 2         //自定义比较器,用于字典序排序
 3         {
 4             int MyStringCompare(String x, String y)
 5             //自定义了字符串比较方法:
 6             //忽略大小写排序,但是大写相对靠前
 7             //如hello,world,World,zoo
 8             //排序后变成hello,World,world,zoo
 9             {
10                 int lx = x.Count(), ly = y.Count(), i;
11                 String xx = x.ToUpper();
12                 String yy = y.ToUpper();
13                 for (i = 0; i < lx && i < ly; i++)
14                     if (xx[i] == yy[i]) continue;
15                     else return xx[i] - yy[i];
16                 if (i == lx && i < ly) return -1;
17                 else if (i < lx && i == ly) return 1;
18                 else
19                 {
20                     for (i = 0; i < lx && i < ly; i++)
21                         if (x[i] == y[i]) continue;
22                         else return y[i] - x[i];
23                     return 0;
24                 }
25             }
26             int IComparer.Compare(Object x, Object y)
27             {
28                 return MyStringCompare(((Data)y).word, ((Data)x).word);
29             }
30         }
31         class myReverserClass2 : IComparer
32         //自定义比较器,用于单词频率排序
33         {
34             int MyStringCompare(String x, String y)
35             //自定义了字符串比较方法:
36             //忽略大小写排序,但是大写相对靠前
37             //如hello,world,World,zoo
38             //排序后变成hello,World,world,zoo
39             {
40                 int lx = x.Count(), ly = y.Count(), i;
41                 String xx = x.ToUpper();
42                 String yy = y.ToUpper();
43                 for (i = 0; i < lx && i < ly; i++)
44                     if (xx[i] == yy[i]) continue;
45                     else return xx[i] - yy[i];
46                 if (i == lx && i < ly) return -1;
47                 else if (i < lx && i == ly) return 1;
48                 else
49                 {
50                     for (i = 0; i < lx && i < ly; i++)
51                         if (x[i] == y[i]) continue;
52                         else return y[i] - x[i];
53                     return 0;
54                 }
55             }
56             int IComparer.Compare(Object x, Object y)
57             {
58                 if (((Data)x).num > ((Data)y).num) return -1;
59                 else if (((Data)x).num < ((Data)y).num) return 1;
60                 else return MyStringCompare(((Data)x).word, ((Data)y).word);
61             }
62         }
View Code

    设计相关方法去掉重复单词,记录次数:

   

 1 static ArrayList Redelete(ArrayList array)
 2         //删掉重复出现的单词,并统计出现次数
 3         {
 4             IComparer myComparer1 = new myReverserClass1();
 5             array.Sort(myComparer1);
 6             for (int i = 0; i < array.Count - 1; i++)
 7             {
 8 
 9                 Data now = (Data)array[i];
10                 Data nxt = (Data)array[i + 1];
11                 now.word = now.word.ToUpper();
12                 nxt.word = nxt.word.ToUpper();
13                 if (now.word.Equals(nxt.word) == true) 
14                 {
15                     array.RemoveAt(i + 1);
16                     Data temp = (Data)array[i];
17                     temp.num++;
18                     array[i] = temp;
19                     i--;
20                 }
21             }
22             return array;
23         }
24         static ArrayList Resort(ArrayList array)
25         //按频率排序
26         {
27             IComparer myComparer2 = new myReverserClass2();
28             array.Sort(myComparer2);
29             return array;
30         }
View Code

 

   (5)对数据调用自定义的Redelete方法和Resort方法,并输出结构到指定文件下

1 static StreamWriter writer;
View Code
1 writer = new StreamWriter(dirpath + "\\" + "12061162.txt");
View Code
 1                 data = Resort(Redelete(data));
 2                 word_word = Resort(Redelete(word_word));
 3                 word_word_word = Resort(Redelete(word_word_word));
 4                 try
 5                 {
 6                     writer.WriteLine("文件地址:" + i);
 7                     writer.WriteLine("最常见2联短语:");
 8                     if (word_word.Count != 0) 
 9                         for (int j = 0; j < Math.Min(word_word.Count,10); j++)
10                             writer.WriteLine(((Data)word_word[j]).word);
11                     else writer.WriteLine("不存在");
12                     writer.WriteLine("最常见3联短语:");
13                     if (word_word_word.Count != 0)
14                         for (int j = 0; j < Math.Min(word_word_word.Count, 10); j++)
15                             writer.WriteLine(((Data)word_word_word[j]).word);
16                     else writer.WriteLine("不存在");
17                     writer.WriteLine("所有单词如下:");
18                     foreach (Data j in data)
19                         writer.WriteLine(j.word + "------" + j.num);
20                 }
21                 catch (UnauthorizedAccessException e)
22                 {
23                     Console.WriteLine(e.ToString());
24                 }            
View Code

4.设计数据,数据如下:

http://pan.baidu.com/s/1mgyYOTM

三. 性能分析与改进

虽然排序用了ArrayList.Sort()方法,但是删除重复时用了ArrayList.RemoveAt()方法,最坏可能是N^2的复杂度,这导致了算法复杂度极大升高,后来看了才意识到。可以调用Dictionary类,减少运行时间。改进代码如下:(课程网站提交的是源代码,想改时发现错过提交时间了)

 

 1 static ArrayList Redelete(ArrayList array)
 2         //删掉重复出现的单词,并统计出现次数
 3         {
 4             IComparer myComparer1 = new myReverserClass1();
 5             array.Sort(myComparer1);
 6             Dictionary<String,int> map = new Dictionary<String,int>();
 7             for (int i = 0; i < array.Count ; i++)
 8             {
 9 
10                 Data now = (Data)array[i];
11                 map.Add(now.word,1);
12                 if (i == array.Count - 1) break;
13                 Data nxt = (Data)array[i + 1];
14                 String temp = now.word.ToUpper();              
15                 nxt.word = nxt.word.ToUpper();
16                 while (temp.Equals(nxt.word) == true) 
17                 {
18                     map[now.word]++;
19                     i++;
20                     if (i + 1 == array.Count) break;
21                     nxt = (Data)array[i+1];
22                     nxt.word = nxt.word.ToUpper();
23                 }
24             }
25             array = new ArrayList();
26             foreach (KeyValuePair<String,int> kvp in map)
27                 array.Add(new Data(kvp.Key, kvp.Value));
28             return array;
29         }
View Code

 

 

这组数据在改进前无法运行

改进后运行状态为:

虽然也很慢,而且cpu运行有时比较高,但是可以出结果了,之前的40min也没出结果。

 从上面看出,我的代码主要运行时间在IComparer比较上,排序时的比较总会调用MyStringCompare,比较一次,调用一次。故占用浪费时间较大。

 因代码编写匆忙,故时间主要花费在实现功能上,而忽略了性能。

 

 四.数据验证

 

 此数据可看出,可以显现扫面三联词汇,二连词汇,统计所有单词词频,可以忽略大小写。故程序正确性无误。

五.感想

虽然不是第一次写C#程序了,但是完成这次作业后才发现,自己C#知识不足,写出的代码风格接近java,对C#特有的一些知识没有掌握。而且前期投入时间不足,导致后期忙于赶任务,完成的不是很好,性能不够快,代码全写在主类中,全是静态方法,风格不是很好。希望这次也给自己一个教训,总结经验,更好地完成下一次作业!

 

发表评论
用户名: 匿名