标准库heapq的使用
转载自: https://blog.csdn.net/y472360651/article/details/80725355
查找最大或最小的N个元素
怎么样从一个列表中取出最大或最小的N个元素的列表?在Python的标准库中,有一个名为heapq的,该模块中具有两个函数nlargest和nsmallest可以完全解决我们的问题,下面我们来看看这两个函数的作用:
import heapq L = [5, 4, 6, 2, 8, 10, 1] # 获取列表中最大的三个元素
print heapq.nlargest(3, L)
# 获取列表中最小的三个元素
print heapq.nsmallest(3, L) # ===========打印结果如下===========
[10, 8, 6]
[1, 2, 4]
两个函数都可以传递参数,用于更复杂的数据结构当中:
import heapq info_list = [
{"name": "laozhang", "age": 20, "score": 90},
{"name": "laoli", "age": 21, "score": 88},
{"name": "laowang", "age": 24, "score": 58},
{"name": "laohe", "age": 22, "score": 77},
{"name": "laoyang", "age": 21, "score": 89}
] # 取出年龄最大的两个数据
print heapq.nlargest(2, info_list, key=lambda item: item["age"]) # ===========打印结果如下===========
[{'name': 'laowang', 'age': 24, 'score': 58}, {'name': 'laohe', 'age': 22, 'score': 77}]
其实,在底层的实现中,heapq首先会将列表数据进行堆排序后放入一个列表:
import heapq L = [5, 4, 6, 8, 2, 7]
# heapify操作之后,会将列表中最小的元素挪到第一位
heapq.heapify(L)
print L # [2, 4, 6, 8, 5, 7] print heapq.heappop(L) # 2
print heapq.heappop(L) # 4
print heapq.heappop(L) # 5
堆数据结构最重要的特征就是,列表的第一个元素永远是最小值。剩余的小值元素可以通过heapq.heappop(iterable)获得。该方法会先将第一个元素弹出来,然后下一个最小的元素来取代被弹出的元素,以此来获得列表L中最小的三个元素为2,4,5。
当查找的元素个数相对比较少时,nlargest和nsmallest函数是很合适的。如果你仅仅想查找唯一一个最大的或最小的值时,那么min和max函数会更快一些。类似的,如果查找元素个数与列表的长度大小接近时,通常先排序这个列表,然后使用切片的方式会更加快一些,我们需要在正确的场合使用nlargest和nsmallest函数才能发挥它们的优势。
实现一个优先级队列
怎么实现一个按优先级排序的队列?并且在这个队列上面每次执行pop操作总是返回优先级最高的那个元素。下面的类使用heaqp模块实现了一个简单的优先级队列:
import heapq class HeapQueue(object):
def __init__(self):
self._queue = []
self._index = 0 def push(self, item, priority):
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1 def pop(self):
return heapq.heappop(self._queue) class Item(object):
def __init__(self, name):
self.name = name def __repr__(self):
return "Item({!r})".format(self.name) q = HeapQueue()
q.push(Item("abc"), 5)
q.push(Item("def"), 1)
q.push(Item("ghi"), 2)
q.push(Item("jkl"), 1) print q._queue
print q.pop() print q._queue
print q.pop() print q._queue
print q.pop() print q._queue
print q.pop() # =============打印结果如下=============
[(-5, 0, Item('abc')), (-1, 1, Item('def')), (-2, 2, Item('ghi')), (-1, 3, Item('jkl'))]
(-5, 0, Item('abc')) [(-2, 2, Item('ghi')), (-1, 1, Item('def')), (-1, 3, Item('jkl'))]
(-2, 2, Item('ghi')) [(-1, 1, Item('def')), (-1, 3, Item('jkl'))]
(-1, 1, Item('def')) [(-1, 3, Item('jkl'))]
(-1, 3, Item('jkl'))
从打印结果观察可以得知,第一个pop()操作返回优先级最高的元素。另外注意到,有两个优先级一样的元素(def和jkl),pop操作是按照它们的插入顺序返回的,先插入的先返回,后插入的后返回。
在上面代码中,队列包含了一个(-priority, self._index, item)元组,优先级为负数的目的是使得元素按照优先级从高到低进行排序,index变量确保同等优先级下,按照插入顺序先后取出,先插入的先取出,后插入的后取出。
首先阐明一点,对象的实例是不能进行排序的,所以我们必须引入一个元组,并对其设置优先级,只要对两个元素的优先级不同就能进行比较,如果两个优先级一样,就需要引入一个index变量,作为辅助排序。如果没有index作辅助排序,那么两个优先级相同的就不能进行比较,将会出错,请看下面错误比较:
a = (1, Item("abc"))
b = (1, Item("def"))
print a < b
# 将会报如下错误:
TypeError: '<' not supported between instances of 'Item' and 'Item'
但是,如果我们引入一个变量index作辅助排序,就能进行比较:
a = (1, 3, Item("abc"))
b = (1, 1, Item("def"))
print(a < b)
#===========打印结果如下===========
False
因为在本示例中,index变量不可能会出现相同的值,所以就可以很好的避免上面的错误。在Python做元组比较时,如果前面的比较可以确定了,后面的操作就不会发生了。
标准库heapq的使用的更多相关文章
- Python标准库模块之heapq – 堆构造
Python标准库模块之heapq – 堆构造 读前福利:几百本经典书籍https://www.johngo689.com/2158/ 原文链接:https://www.johngo689.com/2 ...
- Python3标准库:heapq堆排序算法
1. heapq堆排序算法 堆(heap)是一个树形数据结构,其中子节点与父节点有一种有序关系.二叉堆(binary heap)可以使用一个有组织的列表或数组表示,其中元素N的子元素位于2*N+1和2 ...
- python学习笔记系列----(八)python常用的标准库
终于学到了python手册的最后一部分:常用标准库.这部分内容主要就是介绍了一些基础的常用的基础库,可以大概了解下,在以后真正使用的时候也能想起来再拿出来用. 8.1 操作系统接口模块:OS OS模块 ...
- 【循序渐进学Python】11.常用标准库
安装完Python之后,我们也同时获得了强大的Python标准库,通过使用这些标准库可以为我们节省大量的时间.这里是一些常用标准库的简单说明.更多的标准库的说明,可以参考Python文档 sys 模块 ...
- Python标准库概览
Python标准库通常被称为"自带的电池",自然地提供了广泛的功能,涵盖了大概200个左右的包与模块.不断有高质量的包或模块被开发出来,极大的丰富了标准库.但有些模块放在标准库中很 ...
- Python:标准库(包含下载地址及书本目录)
下载地址 英文版(文字版) 官方文档 The Python Standard Library <Python标准库>一书的目录 <python标准库> 译者序 序 前言 第1章 ...
- python第六天 函数 python标准库实例大全
今天学习第一模块的最后一课课程--函数: python的第一个函数: 1 def func1(): 2 print('第一个函数') 3 return 0 4 func1() 1 同时返回多种类型时, ...
- 转--Python标准库之一句话概括
作者原文链接 想掌握Python标准库,读它的官方文档很重要.本文并非此文档的复制版,而是对每一个库的一句话概括以及它的主要函数,由此用什么库心里就会有数了. 文本处理 string: 提供了字符集: ...
- Python 标准库一览(Python进阶学习)
转自:http://blog.csdn.net/jurbo/article/details/52334345 写这个的起因是,还是因为在做Python challenge的时候,有的时候想解决问题,连 ...
随机推荐
- Python学习路线图(2020年最新版)
这是我刚开始学习python时的一套学习路线,从入门到上手.(不敢说精通,哈哈~) 希望对大家有帮助哈~ 一.Python入门.环境搭建.变量.数据类型 二.Python运算符.条件结构.循环结构 三 ...
- Kafka无法消费?!我的分布式消息服务Kafka却稳如泰山!
在一个月黑风高的夜晚,突然收到现网生产环境Kafka消息积压的告警,梦中惊醒啊,马上起来排查日志. 问题现象:消费请求卡死在查找Coordinator Coordinator为何物?Coordinat ...
- 深度剖析Kubernetes API Server三部曲 - part 3
在本系列的前两部分中我们介绍了API Server的总体流程,以及API对象如何存储到etcd中.在本文中我们将探讨如何扩展API资源. 在一开始的时候,扩展API资源的唯一方法是扩展相关API源代码 ...
- Crossword Expert CodeForces - 1194F (期望)
大意: $n$个题, 按照第$i$题随机$t_i$或$t_i+1$秒钟完成, 最多做$T$秒, 求做题数期望. 期望转为做题数$\ge x$的方案数之和最后再除以总方案数 这是因为$\sum\limi ...
- Swiper 轮播插件 之 动态加载无法滑动
1.原因:轮播图未完全动态加载完成,即初始化 2.方法一:ajax链式编程 $.ajax({ type: "get", url: serviceURL + "/listB ...
- springboot中使用验证码kaptcha
1.pom.xml引入kaptcha所需要的jar包 <!-- 验证码 --> <dependency> <groupId>com.github.penggle&l ...
- 在论坛中出现的比较难的sql问题:3(row_number函数 分组查询)
原文:在论坛中出现的比较难的sql问题:3(row_number函数 分组查询) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所 ...
- .net Core如何对静态文件的访问进行鉴权操作?
之前给公司开发了一个文件管理服务,最基本的功能就是文件的上传下载,以及更新删除.预览:负责公司各个子系统的相关附件的管理,所有的接口都通过AOP来进行身份拦截认证了,但是在进行预览的时候,因为采用的是 ...
- Vue子父组件方法互调
讲干货,不啰嗦,大家在做vue开发过程中经常遇到父组件需要调用子组件方法或者子组件需要调用父组件的方法的情况,现做一下总结,希望对大家有所帮助. 父组件调用子组件方法: 1.设置子组件的ref,父组件 ...
- QT 定时器的使用方法
在界面程序中很容易使用到,定时刷新或者更新什么东西,此时应该使用定时器的功能,定时器是在指定时间触发定时器函数,来达到定时的效果 接下来介绍两种定时器的使用,废话不说直接上代码 代码结构: dialo ...