张宵 20200917-2-词频统计

此作业的要求参见:[https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11206]

 

 一、代码以及版本控制

github地址:https://github.com/ZigHello/learngit.git

coding.net地址:https://e.coding.net/nenuteamwork/spec/nenu_project.git

使用语言:python

二、功能实现及重难点分析

功能1 小文件输入。

实现效果图:

 

 重难点分析:

(1)文件读取

  python中有一个文件读取方法:open(filename,mode,buffering,encoding),其中filename为文件全称,mode为文件的读取模式,buffering为寄存区的缓冲大小,encoding为文件的编码方式。同时文章中会存在大小写等问题,在这里统一将读入的文章的字母转换为小写字母,便于之后分词处理。

1 #文件读取 open(filename,mode,buffering,encoding)方法
2  f = open(text, 'r', -1, 'utf-8')
3 # 读取文本内容并将字母全部转换为小写形式
4  after_txt = f.read().lower()

(2)杂项处理

   对于英文文章的分词,比较容易处理。一般用空格作为一个词的划分标志,但是也注意到文章中有一些标点符或者换行符或者数字等杂项,这里就需要对这些杂项进行处理。可以用正则表达式或者直接用python中的replace(),我只对英文常见的标点符用空格进行替换,做了一个较简单的杂项处理,这里还存在许多瑕疵,可以进一步优化,暂且先实现功能。替换后的文章,用split()就可以很容易的将文章切割成一个个单词。

1 strl_list = str.replace('\n', ' ').replace('.', ' ').replace(',', ' ').\
2                 replace('!', ' ').replace('\\', ' ').replace('#', ' ').\
3                 replace('[', ' ').replace(']', ' ').replace(':', ' ').\
4                 replace('?', ' ').replace('-', ' ').replace('\'', ' ').\
5                 replace('\"', ' ').replace('(', ' ').replace(')', ' ').\
6                 replace('', ' ').replace(';', ' ').lower().split()

 

(3)词频统计

  功能要求对词频计数,同时要求在总计数中相同的单词不重复计数。创建一个空字典,字典的好处在于记录了键值对,便于之后取值。将分割的单词列表循环,如果字典中有该单词,则对于单词的value值+1,否则添加入字典并将改单词的value值置1。最后进行排序,python中有几种排序函数,这里区分一下sort()和sorted()。

  sort 是应用在 list 上的方法sorted 可以对所有可迭代的对象进行排序操作。list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。由于词频统计用字典存储,字典是一个可迭代对象,所以选择了sorted()函数。

1   # 如果字典里有该单词则加1,否则添加入字典
2     for str in strl_list:
3         if str in count_dict.keys():
4             count_dict[str] = count_dict[str] + 1
5         else:
6             count_dict[str] = 1
7     # 按照词频从高到低排列
8     count_list = sorted(count_dict.items(), key=lambda x: x[1], reverse=True)

(3)命令行参数

  Python 中可以用 sys 的 sys.argv 来获取命令行参数:

  • sys.argv 是命令行参数列表。
  • len(sys.argv) 是命令行参数个数。

  还提供了getopt模块是专门处理命令行参数的模块,用于获取命令行选项和参数,提供了两种方法,具体使用方法参见:https://www.runoob.com/python3/python3-command-line-arguments.html

 1      try:
 2             list = read_text(argv[-1])
 3             opts, args = getopt.getopt(argv, "sh", ["ifile", "ofile"])  # 设置命令行参数
 4         except getopt.GetoptError:
 5             print("test.py -i <inputfile> -o <outputfile>")
 6             sys.exit(2)
 7         for opt, arg in opts:
 8             if opt == "-s":  # 命令行参数为-s时执行的操作
 9                 num = len(list)
10                 print('total', num)
11                 print('\n')
12                 for word in list:
13                     print('{:20s}{:>5d}{}'.format(word[0], word[1], '\n'))
14             elif opt == "-h":  # 命令行参数为-h时执行的操作
15           print("please input the parameter")

 

(4)将py文件转换为exe文件

  参照上一届同学的博文:https://www.cnblogs.com/hanhao970620/p/11537088.html

功能2 支持命令行输入英文作品的文件名。

实现效果图:

 重难点分析:

(1)命令行参数

  功能一中的命令行参数有2个,在功能二中的命令行参数只有1个,这里就需要进行分支处理。当len(argv)==2时,进入功能一模块;当len(argv)==1时,进入功能二模块。具体代码请见功能三

1 if len(argv) == 1:
2    #功能一
3 
4 else5    #功能二

(2)数据量

   题目指出文件大小最大为40M,这一点我没有测试,纯文本文件40M是一个相对较大的数据量,没有做压力测试,难以评估程序的健壮性。

功能3 支持命令行输入存储有英文作品文件的目录名,批量统计。

 重难点分析:

(1)区分输入的参数是文件夹名还是文件名

  参考了往届同学的做法,有同学指定了文件夹名,有同学用正则表达式匹配.txt,有同学遍历文件夹。我在这里参照采取了匹配方式,功能二中输入的是文件名.txt,功能三输入的是文件夹名,通过传入参数与正则匹配.txt进行匹配,如果匹配成功,则传入的是文件名,否则是文件夹名。

1 pattern = re.compile('.+\.txt')           #匹配.txt结尾的正则表达式
2 folder_name = argv[-1]                    #argv[-1] 输入参数的最后一个
3 m = re.findall(pattern,folder_name)       #寻找匹配项
4 if len(m) != 0:                           #如果匹配则列表存在元素,为文件名,执行功能二
5     ...
6 else                                      #如果不匹配则列表不存在元素,为文件夹名,执行功能三
7     ...

(2)文件夹的处理

  python中的os.chdir(path) 方法用于改变当前工作目录到指定的路径。path -- 要切换到的新路径。这里path直接指定为同目录下的文件夹名。os.listdir(path) 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。path -- 需要列出的目录路径,这里不用设置。

1  os.chdir(folder_name)             #切换至folder_name文件夹目录
2  filename_list = os.listdir()      #将文件夹下的文件返回

(3)只列出前10个高频单词

  功能一、二均把所有词频列出,功能三要求只列前10,所以可以设置标志位,如果flag == 0,实现功能一、功能二,将所有内容列出;如果flag == 1,实现功能三,如果本身词频不足10个,全部输出,如果大于10个,输出前10。

 1 def argv_2(argv, flag):         #功能二 命令行参数为2
 2     pattern = re.compile('.+\.txt')
 3     folder_name = argv[-1]
 4     m = re.findall(pattern, folder_name)
 5     if len(m) != 0:  # 功能二,参数以.txt结尾的文件名,直接执行词频操作
 6         arry = read_text(argv[-1])
 7         if flag == 0:  # 标志位为0,把所有单词都列出来
 8             print('total', len(arry), 'words')
 9             print('\n')
10             out(arry)
11         else:  # 标志位不为0,只列出前十
12             print('total', len(arry), 'words')
13             print('\n')
14             if len(arry) > 10:
15                 for i in range(10):
16                     print('{:20s}{:>5d}'.format(arry[i][0], arry[i][1]))
17             else:  # 如果本身不超过10个单词量,则列出所有单词即可
18                 out(arry)
19     else:  # 功能三,有多个文件,打开文件夹
20         os.chdir(folder_name)  # 文件夹操作
21         filename_list = os.listdir()
22         for file_name in filename_list:
23             print(file_name[:-4] + '\n')
24             file_list = [file_name]
25             argv_2(file_list, 1)  # 得到文件名,进行递归操作,标志位置1,说明要取前10
26             print('----\n')

 

功能4 支持重定向输入

 

 

 重难点分析:

(1)python中的重定向

   在重定向中'<'符号是标准输入,'>'是标准输出,python可以使用input()方法即可捕捉到输入的文件内容。代码如下:

1 redirect_words = input().lower()        #获取重定向文本信息并把单词转换为小写

 (2)区分功能一和重定向参数

  需要先理解功能一和重定向的参数个数,功能一后面直接接文件名: wf -s text.txt 参数个数为3,重定向:wf -s < text.txt  参数个数为2,所以基于此可以进行分支。随着功能点越多,越发发现抽取函数的重要性,按之前的逻辑,输入-判断-输出全在一块判断,并由大量重复代码。

1 if sys.argv[1] == "-s":
2      #功能一
3      if( len(sys.argv) == 3 ):
4          argv_3(argv, 0)
5      else:
6      #重定向获取文件名
7         redirect()
1 def redirect():#功能四 重定向输入
2     redirect_words = input().lower()  # 获取重定向文本信息并把单词转换为小写
3     count_list = words_split(redirect_words)  # 调用分词逻辑方法
4     print('total', len(count_list))  # 打印结果
5     out(count_list)

 

(3)获取输入数据

  命令行参数只有一个,直接调用input()方法获取输入文本,其他于之前一致。

1 def argv_1(argv, flag): #功能四 命令行输入文本
2     text_contents = input()  # 获取输入数据
3     count_list = words_split(text_contents)  # 调用分词逻辑方法
4     print('total', len(count_list))  # 打印结果
5     out(count_list)

三、PSP

功能实现及测试PSP

PSP阶段 预计花费时间(min) 实际花费时间(min) 时间花费差距原因
功能一 180 320

1.命令行参数设置,对这里完全不知道,花费了很长时间理解

2.对python的不熟悉,排序sorted(),文件读取open()

3.py文件转exe文件,这里查看了前辈的博客,节省了很多精力

功能二 90 120

1.未想到通过命令行参数长度来控制

功能三 150 300

1.区分功能二和功能三,无法判断输入的是文件名还是文件夹名

2.文件夹操作,获取文件夹里的所有文件

3.控制输出词频的两种方式输出前10个词频

功能四(重定向) 90 70

1.python中重定向的方法使用

2.区分功能一和重定向的输入

功能四(控制台输入) 90 40 1.从控制台获取输入数据
posted @ 2020-09-23 09:14  张宵  阅读(264)  评论(0编辑  收藏  举报