题目:通过python分析给定文件中小说(群共享文件 emma.txt)的单词直方图(单词,频率)
分析:
第一步先把文件读进来,简单的文件操作;
第二步把文本按照单词打散,可以通过str.split循环对各个标点进行切分,但是感觉这么做好low,耗时,耗内存,还会产生很多多余的空字符,在后期需要排除,另外像名字后带's这样的单词不好处理,只能暂时先分割成两个单词;
第三步相同的单词合并,计数+1,用字典可以很简单的处理;
第四步根据统计画图,画图还没学,暂时考虑先按照出现次数排序,再打印出来。
1.读文件
with open('emma.txt') as f: text = f.read()
2.把文章打散
最初是这么做的,每发现一个特殊字符,就手动添加一段代码,劳神费力
l1 = text.split('.') print(len(l1)) l2 = [] for i in l1: l2 += i.split(',') print(len(l2)) l3 = [] for i in l2: l3 += i.split('\n') print(len(l3))
既然代码基本是一样的,那么就考虑用循环来合并
last_list = [text] split_str = '''.,'" \n;-_?![]()`:''' for x in split_str: new_list = [] for i in last_list: new_list += i.split(x) last_list = new_list
每次发现新的特殊字符,在split_str中添加一个元素即可
3.计数
因为分割产生了很多空字符串'',所以在循环里面排除掉(实测空字符串高达4W多个)
di = {} for i in last_list : if i=="": continue elif i in di: di[i] += 1 else: di[i] = 1 print("len(di):",len(di))
4.排序
由于sort方法只能对key进行排序,所以这里的方法是从原字典中找出最大的元素,插入到新字典中,完成排序
di2 = {} while len(di)>0: j=0 for i in di: if j==0 : j = i elif di[i]>di[j]: j = i di2[j] = di.pop(j) print("len(di2):",len(di2)) js = json.dumps(di2,indent=1) print(js)
因为一共有7000多个元素,排序操作非常耗时
优化方案:
第二步文章打散,用正则匹配,耗时的双重循环操作瞬间出结果,同时,不会出现空字符串,第三步的排除空字符串的操作也可以去掉了
last_list = re.findall("[a-zA-Z0-9]+", text)
第三步,用get方法取代if判断
di = {} for i in last_list : di[i] = di.get(i, 0) + 1 print("len(di):",len(di))
第四步排序,调换key和value放到列表中,使用sort方法进行排序
di2 = {} t = [] for key, value in di.items(): t.append((value, key)) t.sort(reverse=True) for i in t: di2[i[1]]=i[0]
瞬间排好,效率大增
第一步读取文件可以考虑按行读取,节省内存,但是后面需要改动较大,这里就暂不修改了
总结:
如果可以的话,尽量不要在python中写任何可能耗时的算法,能用库函数解决的就用库函数解决