天天看點

python deque heapq詳解概念擷取最大或者最小的N個元素

概念

deque子產品是python标準庫collections中的一項,它提供了兩端都可以操作的序列,這意味着,在序列的前後你都可以執行添加或删除操作。

使用deque(maxlen=N) 構造函數會建立一個固定大小的隊列。當新的元素加入并且這個隊列已經滿的時候, 最老的元素會被替換掉的。

from collections import deque
q = deque(maxlen=)
q.append()
q.append()
q.append()
print(q) #deque([1, 2, 3], maxlen=3)
q.append()
q.append()
print(q) # deque([3, 4, 5], maxlen=3)
           

可以在隊列的兩端 增加删除

q.appendleft()
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 = [,, ,, , ,,,,]
print(heapq.nlargest(, nums)) #[52, 44, 34]
print(heapq.nsmallest(, nums)) #[1, 2, 3]
           

接受關鍵字參數, 用于複雜的資料結構

portfolio = [
    {'name': 'IBM', 'shares': , 'price': },
    {'name': 'AAPL', 'shares': , 'price': },
    {'name': 'FB', 'shares': , 'price': },
    {'name': 'HPQ', 'shares': , 'price': },
    {'name': 'YHOO', 'shares': , 'price': },
    {'name': 'ACME', 'shares': , 'price': }
]
cheap = heapq.nlargest(, portfolio, key=lambda s: s['price'])
expensive = heapq.nsmallest(, 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 = 

    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 

    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 = PriorityQueue()
q.push(Item('foo'), )
q.push(Item('bar'), )
q.push(Item('spam'), )
q.push(Item('grok'), )

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, (-, , , ))
heapq.heappush(mylist, (-, , , ))
heapq.heappush(mylist, (, , , ))


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)[-]) #5
print(heapq.heappop(mylist)[-])# 7
           

分析:

第一個代表的是權重, 如果使用元組, 相同權重的優先級不能進行比較的。 是以在PriorityQueue 類的push方法 中使用了一個index 就確定了在第一個元素, 權重相同的情況下,就會直接 根據index 來進行排序和權重,這樣 最後一個元素不是可疊代,不能進行排序的時候就不會報錯,又可以取到。 是以中間用一個index 來進行自加, 這樣就避免了這個出現重複的問題權重問題。排序是按照先後順序的。

字典映射等多個值

print('=========')
from collections import defaultdict
d = defaultdict(list)
d['a'].append()
d['a'].append()
d['a'].append()

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()
d['a'].add()
d['b'].add()
print(d) # defaultdict(<class 'set'>, {'a': {1, 3}, 'b': {9}})

           

建立多值映射字典

d = defaultdict(list)
for key, value in pairs:
    d[key].append(value)