从一个集合中查找最大最小的N个元素——Python heapq 堆数据结构
Top N问题在搜索引擎、推荐系统领域应用很广, 如果用我们较为常见的语言,如C、C++、Java等,代码量至少也得五行,但是用Python的话,只用一个函数就能搞定,只需引入heapq(堆队列)这个数据结构即可。今天偶然看到这个库,特意记下之。
先看一个例子:
>>> import heapq
>>> nums = [1,8,2,23,7,-4,18,23,42,37,2]
>>> print heapq.nlargest(3, nums)
[42, 37, 23]
>>>
>>> print heapq.nsmallest(3, nums)
[-4, 1, 2]
是不是很简洁?
我们具体来看一下具体的函数定义。heapq有很多函数,最为堆,队列,可想而知,也就是那些push,pop之类的操作,详细请看官方文档:https://docs.python.org/2/library/heapq.html,在这里,我们只看Top N的两个函数,其他函数在用到的时候查看文档就好了。
1)、heapq.nlargest(n, iterable[, key])
从迭代器对象iterable中返回前n个最大的元素列表,其中关键字参数key用于匹配是字典对象的iterable,用于更复杂的数据结构中。
2)、heapq.nsmallest(n, iterable[, key])
从迭代器对象iterable中返回前n个最小的元素列表,其中关键字参数key用于匹配是字典对象的iterable,用于更复杂的数据结构中。
关于第三个参数的应用,我们来看一个例子就明白了。
>>> portfolio = [
{'name': 'IBM', 'shares': 100, 'price': 91.1},
{'name': 'AAPL', 'shares': 50, 'price': 543.22},
{'name': 'FB', 'shares': 200, 'price': 21.09},
{'name': 'HPQ', 'shares': 35, 'price': 31.75},
{'name': 'YHOO', 'shares': 45, 'price': 16.35},
{'name': 'ACME', 'shares': 75, 'price': 115.65}
]
... ... ... ... ... ... ... >>>
>>> cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
>>> print cheap
[{'price': 16.35, 'name': 'YHOO', 'shares': 45}, {'price': 21.09, 'name': 'FB', 'shares': 200}, {'price': 31.75, 'name': 'HPQ', 'shares': 35}]
>>> expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
>>> print expensive
[{'price': 543.22, 'name': 'AAPL', 'shares': 50}, {'price': 115.65, 'name': 'ACME', 'shares': 75}, {'price': 91.1, 'name': 'IBM', 'shares': 100}]
>>>
从例子中可以看出,key匹配了portfolio中关键字为‘price’的一行。
到此为止,关于如何应用heapq来求Top N问题,相比通过上面的例子讲解,已经较为熟悉了。现在有几个需要注意的地方:
1)heapq.heapify(iterable):可以将一个列表转换成heapq
2)在Top N问题中,如果N=1,则直接用max(iterable)/min(iterable)即可。
3)如果N很大,接近集合元素,则为了提高效率,采用sort+切片的方式会更好,如:
求最大的N个元素:sorted(iterable, key=key, reverse=True)[:N]
求最小的N个元素:sorted(iterable, key=key)[:N]
>>> nums = [1,8,2,23,7,-4,18,23,42,37,2]
>>> max(nums)
42
>>> min(nums)
-4
>>> print sorted(nums, reverse=True)[:3]
[42, 37, 23]
>>> print sorted(nums)[:3]
[-4, 1, 2]
从一个集合中查找最大最小的N个元素——Python heapq 堆数据结构的更多相关文章
- 从集合中查找最值得方法——max(),min(),nlargest(),nsmallest()
从集合中查找最值得方法有很多,常用的方法有max(),min(),nlargest(),nsmallest()等. 一.max()和min() 1.1 入门用法 直接使用max(),min(),返回可 ...
- PHP的排列组合问题 分别从每一个集合中取出一个元素进行组合,问有多少种组合?
首先说明这是一个数学的排列组合问题C(m,n) = m!/(n!*(m-n)!) 比如:有集合('粉色','红色','蓝色','黑色'),('38码','39码','40码'),('大号','中号') ...
- not(expr|ele|fn)从匹配元素的集合中删除与指定表达式匹配的元素
not(expr|ele|fn) 概述 从匹配元素的集合中删除与指定表达式匹配的元素 参数 exprStringV1.0 一个选择器字符串.深圳dd马达 elementDOMElementV1.0 ...
- 从一个集合中过滤另一个集合中存在的项(类似in)
直接贴代码出来: List<PriceMark> list = PriceMarkDAL.m_PriceMarkDAL.GetList("Erp_ProName='TLC7528 ...
- Linq--一个集合中查找另一个集合,需熟悉这种写法
//获取科室与病区授权的护士信息 public List<SYS_ZGKSBQDYK> GetUserWardMapByWardCode(string wardCode) ...
- NoSQLBooster如何MongoDB的部分文档从一个集合拷贝到另外一个集合中
假设MongoDB数据库中存有collection_A和collection_B两个集合,如下图所示: (一)先从集合collection_A中拷贝选择的文档 打开collection_A,看到目前有 ...
- C#算法之向一个集合中插入随机不重复的100个数
一道非常经典的C#笔试题: 需求:请使用C#将一个长度为100的int数组,插入1-100的随机数,不能重复,要求遍历次数最少. 1.最简单的办法 var rd = new Random(); Lis ...
- 【Aaronyang原创】用linq取出一个集合中重复的数据
文章已经迁移:http://www.ayjs.net/2013/07/69/ 文章已经迁移:http://www.ayjs.net/2013/07/69/ 文章已经迁移:http://www.ayjs ...
- mysql 获取一个表中缺失的最小编号
select count(*),t1.`name` from test_id t1INNER JOIN test_id t2on t1.id >= t2.idgroup by t1.id,t1. ...
随机推荐
- C语言冷知识
C语言属强类型语言(1)编程语言分2种:强类型语言和弱类型语言.强类型语言中所有的变量都有自己固定的类型,这个类型有固定的内存占用,有固定的解析方法:弱类型语言中没有类型的概念,所有变量全都是一个类型 ...
- k8s之配置flanneld网络
Flannel是Overlay网络的一种,也是将源数据包封装在另一种网络包里面进行路由转发和通信,目前已经支持UDP.VXLAN.AWS VPC和GCE路由等数据转发方式. Flannel通过给每台宿 ...
- SQL Server日志文件过大 大日志文件清理方法 不分离数据库
SQL Server日志文件过大 大日志文件清理方法 ,网上提供了很多分离数据库——〉删除日志文件-〉附加数据库 的方法,此方法风险太大,过程也比较久,有时候也会出现分离不成功的现象.下面的方式 ...
- python--第九天总结
python 多进程和多线程 多线程可以共享全局变量,多进程不能.多线程中,所有子线程的进程号相同:多进程中,不同的子进程进程号不同. [多进程] Python在2.6引入了多进程的机制,并提供了丰富 ...
- socketserver 模块并发
socketserver是将socket封装的类. 实例: 服务端: import socketserver class Myserver(socketserver.BaseRequestHandle ...
- PEiD中识别虚拟地址和物理地址
可通过PEiD中的信息计算文件偏移地址,从而修改PE文件的关键内容,达到破解目的. 文件偏移地址=相对虚拟地址-节偏移. PEiD中有: 节偏移=虚拟地址VOffset-物理地址ROffset.
- react项目的ant-design-mobile的使用
现在测试一下ant-design-mobile的使用,引用一个Button 没有样式 这个问题是没有引入样式 解决方法有两种 这种方法自己弄不出来,然后用另外一种方法 引入样式: import 'an ...
- Java 后台验证的工具类
Java 后台验证的工具类 public class ValidationUtil { //手机号 public static String mobile = "^( ...
- eclipse定制化配置调优、初始化配置指南、可以解决启动慢等问题
配置eclipse的jvm参数 打开eclipse根目录下的eclipse.ini在最后面加上如下的jvm参数 -Xms400m -Xmx1400m -XX:NewSize=128m -XX:MaxN ...
- c#子线程线程中操作窗体更新的报错
用 在执行上传时,由于操作较长窗体界面卡住,于是用task解决 Task t1 = new Task(manage.UploadData); t1.Start(); 结果不卡了,程序也传完了,运行到更 ...