软工作业 5:结对项目之词频统计——增强功能
一:基本信息
1、编译环境:python3.7
2、成员:1613072028陈志华
1613072029徐东
3、项目地址:
https://gitee.com/ntucs/PairProg/tree/SE028_029
4、作业地址:
https://edu.cnblogs.com/campus/ntu/Embedded_Application/homework/2088
二:项目分析
Task 1. 接口封装 —— 将基本功能封装成(类或独立模块)
import re class wordclass: def process_file(dst): # 读取文件 countline = len(open(dst, 'r').readlines()) # 文本的行数countline with open(dst) as f: bvffer = f.read() f.close() return bvffer def process_buffer(bvffer): if bvffer: for ch in '“‘!;:,.?”': bvffer = bvffer.lower().replace(ch, " ") wordmatch = "^[a-z]{4}(\w)*" #正则表达式至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写 # 将文本内容都改为小写且去除文本中的中英文标点符号 words = [] for i in range(len(bvffer)): word = re.match(wordmatch, bvffer[i]) # 匹配list中的元素 if word: # 匹配成功,加入words words.append(word.group()) # strip()删除空白符(包括'/n', '/r','/t');split()以空格分割字符串 words = bvffer.strip().split() word_freq = {} for word in words: # 对words进行统计 word_freq[word] = word_freq.get(word, 0) + 1 return word_freq, len(words) def output_result(word_freq): if word_freq: sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) for item in sorted_word_freq[:10]: # 输出 Top 10 的单词 print("单词:%s 频数:%d " % (item[0], item[1])) return sorted_word_freq[:10] def result(dst): buffer = wordclass.process_file(dst) word_freq, countwords = wordclass.process_buffer(buffer) print('文本总单词数:' + str(countwords)) print('文本中最多的10个单词及其词频') wordclass.output_result(word_freq)
测试类:
import 作业5_1 import argparse if __name__ == '__main__': parser = argparse.ArgumentParser(description="your script description") # description参数可以用于插入描述脚本用途的信息,可以为空 parser.add_argument('--file', '-file', type=str, default='Gone_with_the_wind.txt', help="读取文件路径")#default属性是默认值,当参数输入错误时使用默认参数 type后表示参数的类型 args = parser.parse_args() # 将变量以标签-值的字典形式存入args字典 path = args.file #通过键值对形式取值 作业5_1.wordclass.result(path) #此处为类的调用
运行结果:
Task 2. 增加新功能
import re class WordCount(): def __init__(self, dst, m, n, o): # dst:文件路径;m:每个词组长度;n:输出的单词数量;o:设定生成文件的存储路径 self.dst = dst self.m = m self.n = n self.o = o def process_file(self): # 读取文件 d = open(self.dst, "r") bvffer = d.read() return bvffer def process_rowCount(self, bvffer): # 计算文章的行数 if bvffer: count = 1 for word in bvffer: # 开始计数 if word == '\n': count = count + 1 return count def process_wordNumber(self, bvffer): if bvffer: bvffer = bvffer.lower() # 将文本中的大写字母转换为小写 for ch in '{}!"#%()*+-,-.\/:;<=>?&@“”[]^_|': bvffer = bvffer.replace(ch, " ") # 将文本中非法字符转化为空格 words = bvffer.split() # 用空格分割字符串 if words: wordNew = [] words_select = '[a-z]{4}(\w)*' for i in range(len(words)): word = re.match(words_select, words[i]) # 如果不匹配,返回NULL类型 if word: wordNew.append(word.group()) word_freq = {} for word in wordNew: # 将正则匹配的结果进行统计 word_freq[word] = word_freq.get(word, 0) + 1 return wordNew, word_freq def process_MPhrase(self, bvffer): # 查找m个单词组成的词组 if bvffer: model = '' for i in range(self.m): model += '[a-z]+' if i < self.m - 1: model += '\s' result = re.findall(model, bvffer) # 正则查找词组 word_freq = {} for word in result: # 将正则匹配的结果进行统计 word_freq[word] = word_freq.get(word, 0) + 1 return word_freq def output_result(self, word_freq): if word_freq: sorted_word_freq = sorted(word_freq.items(), key=lambda v: v[1], reverse=True) for item in sorted_word_freq[:self.n]: # 输出前n个频率最高的单词 print('<' + str(item[0]) + '>:' + str(item[1])) return sorted_word_freq[:self.n] def print_result(self): print('查询路径为:' + str(self.dst) + '的文本') print('统计词组长度为' + str(self.m) + '且词频前' + str(self.n) + '的单词') bvffer = WordCount.process_file(self) # 文件读入缓冲区 lines = WordCount.process_rowCount(self, bvffer) # 计算文章的行数 wordNew, word_freq = WordCount.process_wordNumber(self, bvffer) # 筛选出符合单词标准的单词词组 sum_words = len(wordNew) # 计算出符合单词标准的单词数量 phrase_freq = WordCount.process_MPhrase(self, bvffer) show_sum_words = 'words:' + str(sum_words) show_lines = 'lines:' + str(lines) print(show_sum_words) # 显示文章单词总数 print(show_lines) # 显示文章的行数 itemsPhrase = WordCount.output_result(self, phrase_freq) with open(self.o, 'w+') as w: w.write(show_lines + '\n') w.write(show_sum_words + '\n') # 词组的可视化输出 for itemPhrase in itemsPhrase: item = '<' + str(itemPhrase[0]) + '>:' + str(itemPhrase[1]) + '\n' w.write(item) print('写入' + self.o + '文件已完成!') w.close() def main(): parser = argparse.ArgumentParser(description="your script description") # description参数可以用于插入描述脚本用途的信息,可以为空 parser.add_argument('--i', '-i', type=str, default='Gone_with_the_wind.txt', help="读取文件路径") parser.add_argument('--m', '-m', type=int, default=3, help="输出的单个词组数量") parser.add_argument('--n', '-n', type=int, default=4, help="输出的频率前n个的单词和词组数量") parser.add_argument('--o', '-o', type=str, default='result.txt', help="读取文件路径") args = parser.parse_args() # 将变量以键-值的字典形式存入args字典 dst = args.i m = args.m n = args.n o = args.o obj =WordCount.WordCount(dst, m, n, o) obj.print_result() if __name__ == '__main__': obj = WordCount('Gone_with_the_wind.txt', 2, 8, 're.txt') obj.print_result()
测试结果:
三:性能分析
四: psp表格:
五:其他
5.1 结对编程时间开销:
我们两人对于Python并没有很多的了解,花费了一个礼拜左右的时间来摸索,完成任务。
5.2 结对编程照片:
六:事后分析与总结
6.1 简述结对编程时,针对某个问题的讨论决策过程
停词表可以通过两种方法实现,第一种是直接在Python的文件里,第二种是写在txt文件里然后读取该文件,我们讨论后,决定采用第二种方法,因为第二种比第一种执行效率高;
6.2 评价对方
陈志华对徐东的评价:我觉得我的同伴非常的积极负责,考虑问题比较的深入,对于一些比较敷衍的问题作出了建议和修改;
徐东对陈志华的评价:对于一些难的问题,他总是能给出合理的解决方法,而且他写的博客条理清晰,整体结构合理。
6.3 评价整个过程:关于结对过程的建议
这次结对编程对于我们是比较新奇的编程方式;以往通常是自己独立完成,不会的大多采取他人意见,而这次两个人对于不会的问题或者意见出现分歧是靠两个人查阅资料然后商讨得出结论;收获颇丰。
6.4其他
结对编程很有意义,是一个很不错的体验。