Individual P1: Summary
经过5个小时成功把simple mode写差不多了。。orz 也是蛮拼的。
开始毫无头绪,本能地开始从度娘搜索‘c# 单词统计’= =看了两段代码也算是见过c#的人了。差不多花了我1小时的时间。
然后我觉得simple mode 大概分为下面几个步骤:
- 读文件:根据目录遍历其所有text files,并整合成一个大的result 集合。
我老觉得一开始就用文件的读写不好调bug,没有命令行方便,于是这部分决定最后再憋。一个递归应该憋不了多久吧。。。 - 统计单词:
- 作业对‘单词’进行了重新地定义,因此需要按照新的定义分割result集合。开始想的是用java曾经用到的string.split()函数,把所有的delimiter传进去的方法(毕竟是吴际虐过的学生:))。但马上改成了用正则表达式进行单词匹配,因为我发现delimiter很难枚举出来。好吧其实是发现周围人都在用正则表达式→_→。所谓墙头草。。。
完成正则表达式还有相应的匹配用了大概2个小时。 - 词频统计:
- 作业上要求越快越好。然后我就开始纠结用什么数据结构。本来准备用散列表,但立马改成了Dictionary结构。是的因为发现周围人都在用这个结构。。这样做是有道理的因为Dictionary内部就是用Hashtable构建的,相当于它的升级版。同时考虑到需要处理大小写不敏感的问题——字母相同大小写不同输出的时候要根据字典序选择最靠前的大小写形式。考虑后决定将‘sta_name’作为Tkey,其值一律小写。并创建一个两个元素的集合CountAndName作为TValue(count,printname)。这样既可以记录词频又可以记录当前最靠前的大小写形式。
处理这部分真是醉了,特别感谢MSDN,上面有很多函数的说明对我的帮助很大,再也不用担心不会用函数。用了3个小时写完最主要的部分。 - 输出至文件:这个5分钟吧。。。忽略不计
于是我现在快要爆 炸 了:)我要睡觉,对不起了老师我要翘明天第一节课了你不要怪我
2014.9.23 1:39
-------------------------------------------------------------------------------------------------------------
二、
于是昨天晚上终于写完了ex2,ex3,总计用时入下:
预计用时 实际用时
预习 3h30min 5h
读写文件 30min 30min
文件处理 1h 2h
词频统计 2h 3h
bug 1h 1h
第一次作业看起来很简单,真正上手之后发现还挺难的。。(哪次你觉得不难啊=。 =),通过用时看出来一半时间都用在了学习c#库函数和Hashtable数据结构上,还是有提升空间的!说起来vs真好用啊,不想再碰vc6.0了!
文件读写很简单,但是编程期间要注意,使用StreamWriter写文件时后,要调用.Close()/.Flush() & .Close() 方法,不然是不会将缓冲区的字符写到指定文件的,而且不关StreamWriter也是一件很可怕的是事情@_@。还有就是有个很好用的函数EnumerateFiles,查找目录里的指定文件,酸爽极了
然后就是分词,因为作业队单词的定义与普通单词不一样= =于是要自己写正则表达式,再去分割。这里看到了艺哥对123file识别出错的问题,特意注意了下,在匹配最前面加上\b(匹配非字母数字与字母数字的分界)就可以了。调用.Matches方法得到matches数组,其中包含所有符合正则表达式的match集合。
文件处理,使用Dictionary结构,提供了.addcount(int)和updatePrintName(string)两个方法,前者负责增加统计次数,UpdatePrintName()是问了解决相同拼写但大小写不同的单词的。具体的,首先读入单词将其转换成小写,并以此作为字典的索引查找对应单词,若存在该记录,便与其值((count,PrintName)的结构体)中的PrintName进行字符串比较。如果新的大小写组合A小于字典中存储的B,说明跟据ASCII码A在B之前,因此将B替换为A,否则不做任何改变。这样通过对整个Matches进行foreach 遍历,便可以完成词频统计了。还有最后关于性能的问题,就是调试的时候发现Tolower()函数(将单词转化为小写)消耗了相当可观的时间。最开始这个问题是lxy发现的,将tolower移到foreach循环外,运行速度提高了25%0.0。一会儿研究一下。
bug,主要是性能的调试。最开始我的程序跑35Mb的文件跑了55秒。。。。。。。。。羞 人家都是跑了15,16s的好吗。当时吓尿了都没有截图。。后来发现时因为我吧所有文件的字符都存到了同一个result中。经过lxy点拨,这样就相当于你申请了一个35Mb的数组ORZ 我也是蛮拼的。。。后来修改了方法FindFiles(),将其分为.WalkDir()和ReadFile()每次读进一个文件传入result数组进行处理。这样速度直接降到了7s好吗,整个人都好了,说吧你们想吃什么我请!
但这里还有一个问题,就是在L同学和我的程序,在A电脑上的vs2012跑分别是16s,7s。换到了B电脑上的vs2013跑就变成了16s,20s!有大神可以回答一个下这个问题吗。。。是因为2012和2013版本不同?还是什么。。。纠结
三、性能分析,找不到很大的数据,于是就先拿了lxy的“著名小说大全”跑!(35MB),不多说了,先上图
应该还是数据太少了吧。。。晚上找点儿大的数据测一下。
还有就是那个system.ni.dll是个啥!怎么着辣么大火!你都快炸了你妈知道么!!!
结果如下:
忽略那个88%的加速球我简直不想看它现在已经飙到94了orz以后见到别人就可以问你们知道外国人写文章用什么词用得最多吗?THE!!!
这个结果应该是正确的,跟L同学的一样。
四、测试样例
1、单词识别(1):
FilE File fILE file fILE filE:根据规则,程序应该输出FilE的统计结果。
输出: FilE:6
正确
2、单词识别(2):
123doc doc d123oc doc123 :根据规则,应该只有doc,doc123被判别为合法单词
输出: doc:1
doc123:1
正确
3、分词:
file@file_file file file?file黄file:分别以@,_,两个空格,制表符,中文字符作为分隔符,不知道中文会怎么样啊,求不乱码
输出: file:6
错误!经测试后发现是将file@file_file识别为两个file,找出正则表达式: @"\b[A-Za-z]{3}[A-Za-z0-9]*",原来\b所说的“字母数字”包括了‘_’,因此就把_file跳过了。。。。。为什么要把下划线包括进去呢。。。我真的不知道该怎么办了。。。。大神们在哪里。。。。。。。
已解决!正则表达式增加了一种模式("_单词"),然后再将'_'删除就行了,其实也不是很麻烦-_-
4、从@流年_风殇偷过来的!因为我实在想不出了。。
123file file File FILE :这个真是好变态!!我的智商已被凌辱。。。。乃们测测结果对不对吧。。
输出: File FILE:2
正确(刚被艺哥智商压制了之后又被自己编的程序秒了:)别跟我说话,我就想自己待会儿。)
这个样例真的值得一测哈哈哈
5、extended(1):
aaaa bbbb cccc!dsds:就是个简单的测试~
输出:
ex2: aaaa bbbb:1
bbbb cccc:1
ex3: aaaa bbbb cccc:1
正确
6、extended(2):
这个是从天神@Dubhe那里弄来的hiuhiuhiu。。。。
"how are you
how Are you
fine thank you and YOU
fine Thank you And you
fine thank YOU and"
输出:
ex2模式:
正确
ex3模式:
正确
7、空文件夹
输出: 空txt
正确
8、弄个cpp、h什么的集合。。。
9、大型测试:
就是那个著名小说的文件夹(34.1Mb):
输出大概长这样:
Simple Mode:
ex2:
ex3:
差不多就是这样恩!恩其他同学的测试结果一样。
10、超大型测试!:
还在找。。。。等我一晚上昂。。。
于是就先这样吧!晚上在说。。。
2014.9.24 13:20
----------------------------------------------------------------------------------------------------------------------------------------------
五、感想:
还有很多要学的= =太弱了= =MSDN是个好东西!c#很好用!
具体的。。学习了Hashtable,c#的基本语法,还有正则表达式。