国产成人AV无码一二三区,少女1到100集,国产精品久久久久精品综合紧,巜公妇之诱感肉欲HD在线播放

文章 > Python高级 > 巧用Python字典处理索引统计

巧用Python字典处理索引统计

头像

Python

2019-06-14 10:08:494954浏览 · 0收藏 · 0评论

索引引擎的基本工作原理便是倒排索引, 即将一个文档所包含的文字反过来映射至文档; 这方面算法并没有太多花样可言, 为了增加效率, 索引数据尽可往内存里面搬。 

而基本思路举个简单例子, 现在有以下文档 (分词已经完成) 以及其包含的关键词:

doc_a: [word_w, word_x, word_y]
doc_b: [word_x, word_z]
doc_c: [word_y]

将其变换为

word_w -> [doc_a]
word_x -> [doc_a, doc_b]
word_y -> [doc_a, doc_c]
word_z -> [doc_b]

写成 Python 代码, 便是

doc_a = {'id': 'a', 'words': ['word_w', 'word_x', 'word_y']} 
doc_b = {'id': 'b', 'words': ['word_x', 'word_z']} 
doc_c = {'id': 'c', 'words': ['word_y']} 
  
docs = [doc_a, doc_b, doc_c] 
indices = dict() 
  
for doc in docs: 
  for word in doc['words']: 
    if word not in indices: 
      indices[word] = [] 
    indices[word].append(doc['id']) 
  
print indices

不过这里有个小技巧, 就是对于判断当前词是否已经在索引字典里的分支

if word not in indices: 
  indices[word] = []

可以被 dict 的 setdefault(key, default=None) 接口替换. 此接口的作用是, 如果 key 在字典里, 那么好说, 拿出对应的值来; 否则, 新建此 key , 且设置默认对应值为 default . 但从设计上来说, 我不明白为何 default 有个默认值 None , 看起来并无多大意义, 如果确要使用此接口, 大体都会自带默认值吧, 如下

for doc in docs: 
  for word in doc['words']: 
    indices. setdefault(word, []) .append(doc['id'])

这样就省掉分支了, 代码看起来少很多.

不过在某些情况下, setdefault 用起来并不顺手: 当 default 值构造很复杂时, 或产生 default 值有副作用时, 以及一个之后会说到的情况; 前两种情况一言以蔽之, 就是 setdefault 不适用于 default 需要惰性求值的场景. 换言之, 为了兼顾这种需求, setdefault 可能会设计成

def setdefault(self, key, default_factory): 
  if key not in self: 
    self[key] = default_factory() 
  return self[key]

倘若真如此, 那么上面的代码应改成

for doc in docs: 
  for word in doc['words']: 
    indices.setdefault(word, list ).append(doc['id'])

不过实际上有其它替代方案, 这个最后会提到.

如果说上面只是一个能预见但实际上可能根本不会遇到的 API 缺陷, 那么下面这个就略打脸了.

考虑现在要进行词频统计, 即一个词在文章中出现了多少次, 如果直接拿 dict 来写, 大致是

def word_count(words): 
  count = dict() 
  for word in words: 
    count.setdefault(word, 0) += 1
  return count 
  
print word_count(['hiiragi', 'kagami', 'hiiragi', 'tukasa', 'yosimizu', 'kagami'])

当你兴致勃勃地跑起上面代码时, 代码会以迅雷不及掩脸之势把异常甩到你鼻尖上 --- 因为出现在 += 操作符左边的 count.setdefault(word, 0) 在 Python 中不是一个左值. 怎样, 现在开始念叨 C艹 类型体系的好了吧.

因为 Python 把默认的字面常量 {} 等价于 dict() 就认为 dict 是银弹的思想是要不得的; Python 里面各种数据结构不少, 解决统计问题, 理想的方案是 collections.defaultdict 这个类. 下面的代码想必看一眼就明白

from collections import defaultdict 
  
doc_a = {'id': 'a', 'words': ['word_w', 'word_x', 'word_y']} 
doc_b = {'id': 'b', 'words': ['word_x', 'word_z']} 
doc_c = {'id': 'c', 'words': ['word_y']} 
  
docs = [doc_a, doc_b, doc_c] 
indices = defaultdict(list) 
  
for doc in docs: 
  for word in doc['words']: 
    indices[word].append(doc['id']) 
  
print indices 
  
def word_count(words): 
  count = defaultdict(int) 
  for word in words: 
    count[word] += 1
  return count 
  
print word_count(['hiiragi', 'kagami', 'hiiragi', 'tukasa', 'yosimizu', 'kagami'])

完满解决了之前遇到的那些破事.

此外 collections 里还有个 Counter , 可以粗略认为它是 defaultdict(int) 的扩展.

关注

关注公众号,随时随地在线学习

本教程部分素材来源于网络,版权问题联系站长!

BOBO浏览器| 韩剧《酒醉热吻》| 王一扬| 年轻的嫂子2| 皇上被群臣扒开腿狂C| 女生给男生吃小头头| 透明泳装秀| 年轻朋友的妻子5| 啊灬啊灬啊…快…深的含义| 教练车内含乳挺进她浸画| 同学的母亲中字ID| B站暴躁女RAPPER| 真爱禁区| 《魅魔妈妈》第1季动漫| 禁忌5大结局| 看动漫| 《教授与女学生》伦理| 星空无限MV国产剧苏畅| 阴部按摩出水太尴尬怎么办| 狗和女人戴避孕套会传染吗| PPT成品网站1688免费| 男朋友摸完小花园小肚子有点痛| 二女片免费观看电视剧杨贵妃传| 韩国电影火热的邻居高清完整版免.| 《部长你别这样》大结局 | 《美式保罗1980》完整版| 蜜桃成熟3D| 少女哔哩哔哩免费高清观看2 | 吻戏刺激| 少女配狗播放视频| 可切换老司机模式浏览器| 公交车NP粗暴H强J玩弄| 《熟妇的荡欲》免费看| 透明女仆服装开裆连体衣| 哥布林杀手| 中文在线字幕免费观看电视剧00..| 小学生自愈扣出桨的三个基本原则| 双色球开奖结果查询| 天美麻花高清在线看电视剧| 游览器| 《落魄贵族当女仆》樱花动漫