• 单词统计,top10 问题,没有用正则


    统计单词出现次数(不是频率)

    基本实现版本:

     1 def cw_words(d = {}):
     2     def makekey(s: str):
     3         chars = set(r"""! '"#$%^&*()_+~=-><.,?/}{][:;""")  # 因为有反斜杠,所以加r,用集合,查找快
     4         ret = []
     5         if 'path' in s:
     6             for i, c in enumerate(s):
     7                 if c in chars:
     8                     ret.append(' ')  # 遇到特殊字符,就用空格替代
     9                 else:
    10                     ret.append(c.lower())
    11         return ''.join(ret).split()
    12 
    13     def makekey1(s: str):
    14         chars = set(r"""! '"#$%^&*()_+~=-><.,?/}{][:;""")  # 因为有反斜杠,所以加r
    15         ret = []
    16         start = 0
    17         if 'path' in s:
    18             for i, c in enumerate(s):  # d..  ..a
    19                 if c in chars:
    20                     if start == i:  # 如果紧挨着还是特殊字符start一定等于i
    21                         start += 1  # 加1
    22                         continue
    23                     ret.append(s[start:i].lower())
    24                     start = i + 1  # 加1 是跳过这个不需要的特殊字符c
    25             else:
    26                 if start < len(s):  # 小于,说明还是有效的字符,而且一直到末尾
    27                     ret.append(s[start:].lower())
    28         return ret
    29 
    30     with open('sample.txt', encoding='utf-8') as f:
    31         for line in f:
    32             words = line.split()
    33             for i in words:
    34                 if 'path' not in i or i == []:
    35                     words.remove(i)
    36             for wordlist in map(makekey, words):  # 每个都拿上去 映射一次
    37                 for word in wordlist:
    38                     d[word] = d.get(word, 0) + 1
    39     new_d =  sorted(d.items(), key=lambda item: item[1], reverse=True)
    40     print(new_d[0])
    41     return new_d[0]
    42 
    43 cw_words()

    优化版本:

      1 #   No 2 对之前版本的优化  封装
      2 '''
      3 优化点:
      4     1、对一些没必要的单词的过滤
      5     2、没有必要 先把每一行切一遍,在到makekey中再切一遍,直接对每一行切,但是之前的chars中需要添加一个 空格了,
      6     3、之前是把切割之后的放在列表中,这样导致用到了很大的额外空间,所以这里使用了yield生成器,用一个出一个
      7     5、因为现在取前10 个,所以排序的时候, 没必要全部打印,所以只选取前10 个即可,
      8             这里推荐使用的方法:
      9                     1、计数的方法,出一个+1
     10                     2、切片取10个,因为之前用了yield,所以这里并不是所有的都取出来,而是只去了10个
     11     6、封装,尽量将所有的不需要别人看到的数据封装起来,此时,注意传参的问题。
     12 
     13 
     14 # print('a','
    ','------')
     15 # a
     16 #  ------
     17 # print('a','\n','------') # 转义
     18 # a 
     ------
     19 # print('a','/
    ','------')
     20 # a /
     21 #  ------
     22 '''
     23 def top10(filename):
     24     def makekey(s: str):
     25         chars = set(r"""! '"#$%^&*()_+~=-><.,?/}{][:;""")  # 因为有反斜杠,所以加r,用集合,查找快
     26         key = s.lower()
     27         ret = []
     28         for i, c in enumerate(key):
     29             if c in chars:
     30                 ret.append(' ')  # 遇到特殊字符,就用空格替代
     31             else:
     32                 ret.append(c)
     33         print(ret)  # ['o', 's', ' ', 'p', 'a', 't', 'h'] ,连起来 ,在空白切开
     34         return ''.join(ret).split()
     35 
     36     def makekey1(line: str, chars = set("""! '"#$%^&*()_+~=-><.,?/\}{][:; 
    """) ):
     37          # 因为有反斜杠,所以加r,加一个空格
     38 
     39          # 这块切割是关键点,一个一个字符对应切
     40          # i 是控制索引,start 是切割的开头
     41          # 每次遇到特殊字符的时候,从start开始切,并且start要移动到现在i + 1 的位置,作为下次的起点
     42          # 如果下次还是特殊字符,此时i =  start,不切,继续往下,但是start继续往前,i+ 1
     43          #如果某次开始都往下都没有在发现特殊字符,就进入else语句,并且,从之前 start开始到最后都是字母,
     44         start = 0
     45         for i, c in enumerate(line):# Split the pathname path into a pair (root, ext) such that root + ext == path
     46             if c in chars:
     47                 if start == i:  # 如果紧挨着还是特殊字符start一定等于i
     48                     start += 1  # 加1
     49                     continue
     50                 yield line[start:i]
     51                 start = i + 1  # 加1 是跳过这个不需要的特殊字符c
     52         else:
     53             if start < len(line):  # 小于,说明还是有效的字符,而且一直到末尾
     54                 yield line[start:]
     55 
     56     def wordcount(filename, encodiong='utf-8', ingore={'a','to','the'}):
     57         d = {}
     58         with open(filename, encoding='utf-8') as f:
     59             for line in f:
     60                 # words = line.split()
     61                 for word in map(str.lower, makekey1(line)):  # 每一行 都拿去切割,每次需要的时候去取回一个 ,给map
     62                     # 这里的先后顺序是:word 去map取,map在去makekey取
     63                     if word not in ingore:
     64                         d[word] = d.get(word, 0) + 1
     65         return d
     66         # no 1  通过 i 控制,和no2 的count是一样的
     67         # for i, (k, v) in enumerate(sorted(d.items(), key=lambda item: item[1], reverse=True)):
     68         #     if i == n:break
     69         #     yield (k, v)
     70         # no 3
     71         # yield  from sorted(d.items(), key=lambda item: item[1], reverse=True)[:n] # n通过传参获取
     72     # no 2
     73     def _top(d):
     74         count = 1
     75         for i in sorted(d.items(), key=lambda item: item[1], reverse=True):
     76             yield i
     77             count += 1
     78             if count > 10:
     79                 break
     80     return _top(wordcount(filename))
     81 
     82 # NO 1 for 循环迭代
     83 # for i in top10('sample.txt'):
     84 #     print(i)
     85 # NO 2list迭代器生成
     86 print(list(top10('sample.txt')))
     87 
     88 '''
     89 单词统计:
     90         1、利用map映射,只是没有用到reduce,大数据的处理,mapreduce
     91         2、一般按照行处理,是比较合适的。
     92         3、生成器、装饰器是python的精华,所以要往这个方向考虑,一般一批一批,一个一个都是可以使用生成器的
     93             思路:返回一个列表,如果直接全部用可以用list,但是不需要可以惰性求值,通过for循环迭代
     94                   惰性求值:多个惰性求值一起使用,要一个,拿一个。
     95                   map(str.lower(), makekey(line)):先找map要一个,map 在找makekey要一个
     96             出现次数 != 出现频率
     97 
     98             排序取前几个:
     99                 1、全排,切片
    100                 2、计数,够了就不取了
    101         4、如果遍历,首选set, dict
    102         5、stopwords = set()  专用词,停止词,遇到就停止
    103 '''
    为什么要坚持,想一想当初!
  • 相关阅读:
    NHibernate中的Clear和Flush方法
    什么是POCO类
    node-vuecli 脚手架安装
    layui表单引入ueditor遇坑记
    PHP的九个超全局变量
    PHP的八个魔术常量
    PHP的七个数组指针函数
    TP6.0多应用模式隐藏路由中的应用名
    TP6.0中的密码验证逻辑、验证器的使用
    Vue 侦听器 watch
  • 原文地址:https://www.cnblogs.com/JerryZao/p/9600744.html
Copyright © 2020-2023  润新知