20200917-2 词频统计

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

github链接:https://github.com/suihao228491/homework1

词频统计 SPEC

老五在寝室吹牛他熟读过《鲁滨逊漂流记》,在女生面前吹牛热爱《呼啸山庄》《简爱》和《飘》,在你面前说通读了《战争与和平》。但是,他的四级至今没过。你们几个私下商量,这几本大作的单词量怎么可能低于四级,大家听说你学习《构建之法》,一致推举你写个程序名字叫wf,统计英文作品的单词量并给出每个单词出现的次数,准备用于打脸老五。

希望实现以下效果。以下效果中数字纯属编造。

功能1 小文件输入。 为表明程序能跑,结果真实而不是迫害老五,请他亲自键
盘在控制台下输入命令。

>type test.txt
My English is very very pool.

>wf -s test.txt
total 5

very    2
my      1
english 1
is      1
pool    1

为了评估老五的词汇量而不是阅读量,total一项中相同的单词不重复计数数,出现2
次的very计数1次。

因为用过控制台和命令行,你早就知道,上面的">"叫做命令提示符,是操作系统的一部分,而不是你的程序的一部分。

此功能完成后你的经验值+10.

核心代码:

def reads(path):   #读取文件
        f = open(path, encoding='utf-8')
        words = re.findall(r'\w+', f.read().lower())#转为小写字母
        return words

def txt_conts(words):  #统计文件数目并打印前10个出现最多词汇
        cnt = Counter(words)
        sum = 0
        for i in cnt:
            sum = sum + 1
        if sys.argv[1] == '-s':
            print('total ', sum)
        else:
            print('total  {} words'.format(sum))
        list1 = cnt.most_common(10)#使用Counter自带排序
        for i in range(10):
             word, count = list1[i]    #解包
             print("{0:<10}{1:>5}".format(word, count)

运行结果截图:

这是词频统计的第一个功能耗时较多,本来是想用麻烦C语言来做的可是太过麻烦,就换成了python。由于对python不是特别熟悉所以没思路的时候有参考别人的代码同时查阅官方文档。

reads函数读取文件进行小写转换排除英语大小写不同的相同字母情况返回文件内容,学习使用了Counter容器这个非常好用一开始自己在尝试编写失败后转而使用了该模块most_common直接

进行排序输出。

class collections.Counter([iterable-or-mapping])

一个 Counter是一个 dict 的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数。 Counter 类有点像其他语言中的 bags或multisets。

most_common([n])

返回一个列表,其中包含 n 个最常见的元素及出现次数,按常见程度由高到低排序。 如果 n 被省略或为 None,most_common() 将返回计数器中的 所有 元素。 计数值相等的元素按首次出现的顺序排序。

Counter类的相关文档链接:https://docs.python.org/zh-cn/3.8/library/collections.html?highlight=counter#collections.Counter

功能2 支持命令行输入英文作品的文件名,请老五亲自录入。

>wf gone_with_the_wand
total  1234567 words

the    5023
a      4783
love   4572
fire   4322
run    3822
cheat  3023
girls  2783
girl   2572
slave  1322
buy

 

822

此功能完成后你的经验值+30. 输入文件最大不超过40MB. 如果你的程序中途崩
了,会被老五打脸,不增加经验值。

核心代码:

def doCount(argvs):  # 对文件名进行更改
            str = '.txt'
            if str in argvs:
                    path = argvs
            else:
                    path = argvs + str
            txt_conts(reads(path))

运行结果:

 这个功能的关键点在于如何判断输入的命令行参数是功能一还是功能二,功能一在计算total时没有words,而功能二是有的,这部分的关键就是输入不带后缀的文件名如何让程序

识别出来并作出相应的处理,为其后面加上.txt后缀名则可以按照功能一进行处理。

功能3 支持命令行输入

>dir folder
gone_with_the_wand
runbinson
janelove
>wf folder
gone_with_the_wand
total 1234567 words
the 5023
a 4783
love 4572
fire 4322b
run 3822
cheat 3023
girls 2783
girl 2572
slave 1322
buy 822
----
runbinson
total 1234567 words
friday    5023
sea       4783
food      4572
dog       4322
run       3822
hot       3023
cood      2783
cool      2572
bible     1322
eat        822
----
janelove
total  1234567 words

love    5023
chat    4783
lie     4572
run     4322
money   3822
inheritance     3023
class   2783
attribute       2572
data    1322
method  822

因为单词量巨大,只列出出现次数最多的10个单词。
此功能完成后你的经验值+8.

核心代码:

def Dic_word(path):#读取文件夹
        paths = 'D:\Project1\homework2\\' + path
        for root, subdir, file_list in os.walk(paths):
                for file in file_list:
                        file_path = os.path.join(root, file)
                        filename = os.path.splitext(file)[0]
                        print(filename)
                        f = open(file_path, 'r', encoding='utf-8')
                        words = re.findall(r'[a-z0-9^-]+', f.read().lower())
                        cnts = Counter(words)
                        sums = 0
                        for i in cnts:
                            sums = sums + 1
                        print('total     {} words'.format(sums))
                        list1 = cnts.most_common(10)  # 使用Counter自带排序
                        for i in range(10):
                                word, count = list1[i]  # 解包
                                print("{0:<10}{1:>5}".format(word, count))
                        print('-----------')
                        f.close()

运行结果:

 

 

 

 这个功能可以算是最难耗时最多的部分主要是我不会读取python的文件在进行了很多的学习编写后代码可以读取文件夹下所有文件名但是不能够访问其中的内容,这个难题的处理困扰了我很长的时间,后面在学长建议帮助下使用了路径拼接保存的方法才得以访问由于第一个功能是通过命令行参数来确认第一个还是第二个功能的所有在功能三我重新编写了打印英语词汇统计的部分。使用的方法和功能一几乎相同使用Counter的内置函数来进行打印前十个出现次数最多的词汇。

功能4 从控制台读入英文单篇作品,这不是为了打脸老五,而是为了向你女朋
友炫酷,表明你能提供更适合嵌入脚本中的作品(或者如她所说,不过是更灵活
的接口)。如果读不懂需求,请教师兄师姐,或者 bing: linux 重定向,尽管
这个功能在windows下也有,搜索关键词中加入linux有利于迅速找到。

>wf -s < the_show_of_the_ring

total 176
the  6
a    3
festival   2
dead 2
for 2
...

>wf
A festival for the dead is held once a year in Japan. The festival is
a cheerful occation, for the dead are said to return to their homes
and they are welcomed by the living.

total 176
the  6
a    3
festival   2
dead 2
for 2
...

此功能完成后你的经验值+10.

核心代码:

def  function_four():#重定向
         str = input()
         filename = "D://python//Scripts//dist//test.txt"
         with open(filename, "w") as f:
               f.write(str)
               file = 'test.txt'
               doCount(file)

结果:

 

 难点在于对于重定向的理解和掌握查阅了很多的资料。

功能5 此功能为选做题,如果完成正确得30经验值,如果不做得0经验值,不会倒扣分数。

你完成了所有功能,后面的博客、PSP等也都精心准备了,去食堂的路上心情大悦。坐下挠了挠手机访问cnblogs上的班级,却发现大家的作业也都非常优秀,自己并不突出,心下黯然。怎么才能更加杰出呢?一抬头,看到老杨老师和和邹欣老师正坐桌对面吃饭,你说出了自己的困惑。

老杨说,“精益求精,一步步榨出自己的潜力来,正是走向杰出的开始啊。”

你说,“老师你具体点呗。”

邹欣老师说,“这样,我想知道5个字母的单词中最频繁出现的是哪10个单词,top10,你怎么办呢?”

你一下就想到了,说了思路,应该blablabla。邹欣老师又问,“6个字母的单词中最频繁出现的是哪10个单词呢,top10?”

老杨追问,“6个字母的字母的单词中最频繁出现的是哪100个单词呢,top100?”

你问,“算法我想好了,性能估计也没问题,命令行参数老师怎么规定呢?”

老杨说,"你来规定,写个简单的文档,包括如何运行,给出运行实例的截图。"

"可变的参数就是(1)几个字母和(2)排行前多少是吧?没有问题。"

此时,你想起自己一直做作业还没有吃饭。肚子咕咕叫得声音如此之大,把你吵醒了。是赶紧去吃饭呢,还是做完这题再说?

功能实现

(以上每1经验值对应 1分。)
要求在同一个可执行程序中实现全部功能,而不是每个功能单独用一个可执行程序实现。

核心代码:

def num_conts(path):  #功能5统计不同字母的最大前n个
        words = reads(path)
        cnt = Counter(words)
        sum = 0
        for i in cnt:
                sum = sum + 1
        print('total     {} words'.format(sum))
        j = 0
        maxwords = cnt.most_common()
        for i in range(sum):
            word, count = maxwords[i]
            if len(word) == int(sys.argv[2]):
                    print("{0:<10}{1:>5}".format(word, count))
                    j = j + 1
            if j == int(sys.argv[3]):
                    break

运行结果:

 

 这个功能的实现就是通过控制台命令参数来确定输出几个单词的字母和一共输出多少个最多的词汇,这个功能的实现难点在于主函数的控制如何保证功能五和功能二

的不会冲突。

主函数代码:

def main(argv):#主函数
        if sys.argv[1] == '-s':#重定向或者功能一
               if len(sys.argv) == 3:
                    doCount(sys.argv[2])
               else:# 重定向1
                    function_four()
        elif os.path.isdir(sys.argv[1]):# 功能三
               Dic_word(sys.argv[1])
        elif  len(sys.argv) == 4 and( 1<=int(sys.argv[2]) or int(sys.argv[2])<=10 ):#功能五
               num_conts(argv[1])
        else:

doCount(sys.argv[
1]

这里在实现功能二和五的判断下将命令行参数第二个转为整形判断同时根据命令参数的多少来进行判断达到了目的。

 PSP

 

 


 

posted @ 2020-09-23 19:29  又是夏了  阅读(320)  评论(0编辑  收藏  举报