概念
deque模块是python标准库collections中的一项,它提供了两端都可以操作的序列,这意味着,在序列的前后你都可以执行添加或删除操作。
使用deque(maxlen=N) 构造函数会新建一个固定大小的队列。当新的元素加入并且这个队列已经满的时候, 最老的元素会被替换掉的。
from collections import deque
q = deque(maxlen=3)
q.append(1)
q.append(2)
q.append(3)
print(q) #deque([1, 2, 3], maxlen=3)
q.append(4)
q.append(5)
print(q) # deque([3, 4, 5], maxlen=3)
可以在队列的两端 增加删除
q.appendleft(6)
print(q) #deque([6, 3, 4], maxlen=3)
p = q.pop()
print(p) #4
print(q) #deque([6, 3], maxlen=3)
print(q.popleft()) #6
获取最大或者最小的N个元素
使用heapq 解决
import heapq
"""获取最大或者最小的元素"""
nums = [1,3, 9,10, 44, 32,2,34,52,21]
print(heapq.nlargest(3, nums)) #[52, 44, 34]
print(heapq.nsmallest(3, nums)) #[1, 2, 3]
接受关键字参数, 用于复杂的数据结构
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.nlargest(3, portfolio, key=lambda s: s['price'])
expensive = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
print(cheap)
# [{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
print(expensive)# [{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
以上进行比较的时候是根据price 进行比较的, 支持key , 就像是sorted 排序一样
总结:
对于取最大值最小值, 几种方法比较和使用
- heapq.nlargest() : 当查找的元素个数相对比较小的时候
- max(),min() : 当仅仅查找唯一的最大值最小值时候
- sorted(items, key=) [:N】: 当N的大小和集合的大小比较接近时候,通常先排序再切片操作
heapq 的使用
下面是对应的函数
heapq.heappush(heap, item) 把item添加到heap中(heap是一个列表)
heapq.heappop(heap) 把堆顶元素弹出,返回的就是堆顶
heapq.heappushpop(heap, item) 先把item加入到堆中,然后再pop,比heappush()再heappop()要快得多
heapq.heapreplace(heap, item) 先pop,然后再把item加入到堆中,比heappop()再heappush()要快得多
heapq.heapify(x) 将列表x进行堆调整,默认的是小顶堆
heapq.merge(*iterables) 将多个列表合并,并进行堆调整,返回的是合并后的列表的迭代器
heapq.nlargest(n, iterable, key=None) 返回最大的n个元素(Top-K问题)
heapq.nsmallest(n, iterable, key=None) 返回最小的n个元素(Top-K问题)
实现按照优先级排列的队列
print("heapq 是基于heap 堆的优先排序的算法")
import heapq
class PriorityQueue(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)[-1]
class Item(object):
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('spam'), 4)
q.push(Item('grok'), 1)
print(q.pop()) # Item('bar')
print(q.pop()) # Item('spam')
print(q.pop()) # Item('foo')
按照优先级等级(下面这个是上面的简化版)
import heapq
import random
# mylist = list(random.sample(range(100), 10))
mylist = []
heapq.heappush(mylist, (-3, 2, 3, 5))
heapq.heappush(mylist, (-6, 2, 3, 1))
heapq.heappush(mylist, (5, 2, 3, 7))
print(mylist) #[(-6, 2, 3, 1), (-3, 2, 3, 5), (5, 2, 3, 7)]
print(heapq.heappop(mylist)) # (-6, 2, 3, 1)
print(heapq.heappop(mylist)[-1]) #5
print(heapq.heappop(mylist)[-1])# 7
分析:
第一个代表的是权重, 如果使用元组, 相同权重的优先级不能进行比较的。 所以在PriorityQueue 类的push方法 中使用了一个index 就确保了在第一个元素, 权重相同的情况下,就会直接 根据index 来进行排序和权重,这样 最后一个元素不是可迭代,不能进行排序的时候就不会报错,又可以取到。 所以中间用一个index 来进行自加, 这样就避免了这个出现重复的问题权重问题。排序是按照先后顺序的。
字典映射等多个值
print('=========')
from collections import defaultdict
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['a'].append(4)
print(d) # defaultdict(<class 'list'>, {'a': [1, 2, 4]})
print(d['a']) #[1, 2, 4]
print("======set()")
d = defaultdict(set) # 是list 添加还是set添加在defaultdict() 中定义
d['a'].add(1)
d['a'].add(3)
d['b'].add(9)
print(d) # defaultdict(<class 'set'>, {'a': {1, 3}, 'b': {9}})
创建多值映射字典
d = defaultdict(list)
for key, value in pairs:
d[key].append(value)