最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 巧用Python字典处理索引统计

    正文概述    2020-03-01   239

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

    巧用Python字典处理索引统计

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

    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) 的扩展.


    下载网 » 巧用Python字典处理索引统计

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元