heapq
模块有两个函数–nlargest()
和nsmallest()
正好能解决我们的问题。
>>> print(heapq.nlargest(3, nums))
[43, 23, 8]
>>> print(heapq.nsmallest(3,nums))
[-1, 1, 2]
#another
import heapq
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'])
expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
print(cheap)
print(expensive)
# 输出
[{'shares': 45, 'name': 'YHOO', 'price': 16.35}, {'shares': 200, 'name': 'FB', 'price': 21.09}, {'shares': 35, 'name': 'HPQ', 'price': 31.75}]
[{'shares': 50, 'name': 'AAPL', 'price': 543.22}, {'shares': 75, 'name': 'ACME', 'price': 115.65}, {'shares': 100, 'name': 'IBM', 'price': 91.1}]
简单的介绍一下heapq
中的方法:
import heapq
#heapq.heappush(heap,item) #heap为定义堆,item 增加的元素;
#eg.
heap=[]
heapq.heappush(heap, 2) # heap = [2]
#heapq.heapify(list) #将列表转换为堆
#eg.
list=[5,8,0,3,6,7,9,1,4,2]
heapq.heapify(list)
#heapq.heappop(heap) #删除最小的值
#eg.
heap=[2, 4, 3, 5, 7, 8, 9, 6]
heapq.heappop(heap) ---->heap=[3, 4, 5, 7, 9, 6, 8]
#heapq.heapreplace(heap, item) #删除最小元素值,添加新的元素值
#eg.
heap=[2, 4, 3, 5, 7, 8, 9, 6]
heapq.heapreplace(heap, 11) ------>heap=[2, 3, 4, 6, 8, 5, 7, 9, 11]
#heapq.heappushpop(heap, item) #首判断添加元素值与堆的第一个元素值对比,如果大于则删除最小元素,然后添加新的元素值,否则不更改堆
#eg.
条件:item >heap[0]
heap=[2, 4, 3, 5, 7, 8, 9, 6]
heapq.heappushpop(heap, 9)---->heap=[3, 4, 5, 6, 8, 9, 9, 7]
条件:item
heap=[2, 4, 3, 5, 7, 8, 9, 6]
heapq.heappushpop(heap, 9)---->heap=[2, 4, 3, 5, 7, 8, 9, 6]
#heapq.merge(...) #将多个堆合并
#heapq.nlargest (n, heap) #查询堆中的最大元素,n表示查询元素个数
#eg.
heap=[2, 3, 5, 6, 4, 8, 7, 9]
heapq.nlargest (1, heap)--->[9]
#heapq.nsmallest(n, heap) #查询堆中的最小元素,n表示查询元素个数
#eg.
heap=[2, 3, 5, 6, 4, 8, 7, 9]
heapq.nlargest (1, heap)--->[2]
nlargest
和nsmallest
是最合适的。min
、max
是最合适的。N
和集合本身相差不大,使用排序并切片的方式是合适的(sorted(items)[:N]
、sorted(items)[-N:]
)。N
相对总元素较少的时候,适合使用将数据转化成列表,元素顺序以堆的顺序排列(参照上述的heapq.heapify()
)。import heapq # 堆的数据结构,通过对数时间能找到最大或最小元素
class PriorityQueue:
def __init__(self):
self._queue = [] #初始化的列表
self._index = 0 # 初始化的索引,用去比较优先级相同的元素
def push(self, item, priority):
# 通过heappush向_queue列表中添加一个元素(元组),默认是小顶堆,因此将优先级取反;
# 元组比较大小是逐项的,因此添加_index作为相同优先级比较的第二个比较项;永远不会比较第三项
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1
def pop(self):
return heapq.heappop(self._queue)[-1] #弹出的是三元组(-priority, _index, Item(''),只显示最后一项即可
#构造的元素类
class Item:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Item({!r})'.format(self.name)
q = PriorityQueue()
q.push(Item('foo'), 1)
q.push(Item('bar'), 5)
q.push(Item('barm'), 4)
q.push(Item('grok'), 1)
print(q.pop())
print(q.pop())
print(q.pop())
print(q.pop())
输出:
Item('bar')
Item('barm')
Item('foo')
Item('grok')
从输出中我们看出:是按照优先级输出,相同优先级的按照索引较小的先输出(因为是小顶堆并且先插入的索引值较小)