单词统计,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','\n','------')
 15 # a
 16 #  ------
 17 # print('a','\\n','------') # 转义
 18 # a \n ------
 19 # print('a','/\n','------')
 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("""! '"#$%^&*()_+~=-><.,?/\\}{][:; \n""") ):
 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 '''

 

posted @ 2018-09-06 20:27  JerryZao  阅读(253)  评论(0编辑  收藏  举报