以下代碼對Patrick Haugh的答案使用了類似的策略,只是它也保留了您的字典。正如在帕特里克的回答中,我們把功率值放在元組的起始位置,這樣它就可以通過堆正確排序。我們將整數鍵附加到進入堆的元組末尾,因爲我們需要它刪除已被取代的字典項。
一旦達到所需的尺寸限制,我們只需要檢查當前最小的物品。如果最小項目小於新項目,則會被替換。
要測試update
代碼,我創建了一個生成器,datagen
,它會生成假數據。爲了保持輸出管理,我已經減少了尺寸的前20名,而不是一個50強
from random import seed, randint
from heapq import heappush, heapreplace
seed(42)
# Make some fake data, in this form: (power, x_pos, y_pos, z_pos)
def datagen():
m = (100., 1., 1., 1.)
while True:
yield tuple(randint(1, 100) * u for u in m)
top20 = {}
heap = []
# Update the heap & the dict
def update(k, tup):
if len(top20) < 20:
heappush(heap, tup + (k,))
top20[k] = tup
elif tup[0] > heap[0][0]:
old = heapreplace(heap, tup + (k,))
top20[k] = tup
del top20[old[-1]]
print('replaced', old[0])
# Test
for k, tup in zip(range(50), datagen()):
print(k, tup)
update(k, tup)
輸出
0 (8200.0, 15.0, 4.0, 95.0)
1 (3600.0, 32.0, 29.0, 18.0)
2 (9500.0, 14.0, 87.0, 95.0)
3 (7000.0, 12.0, 76.0, 55.0)
4 (500.0, 4.0, 12.0, 28.0)
5 (3000.0, 65.0, 78.0, 4.0)
6 (7200.0, 26.0, 92.0, 84.0)
7 (9000.0, 70.0, 54.0, 29.0)
8 (5800.0, 76.0, 36.0, 1.0)
9 (9800.0, 21.0, 90.0, 55.0)
10 (4400.0, 36.0, 20.0, 28.0)
11 (9800.0, 44.0, 14.0, 12.0)
12 (4900.0, 13.0, 46.0, 45.0)
13 (7800.0, 34.0, 6.0, 94.0)
14 (5900.0, 69.0, 16.0, 49.0)
15 (1100.0, 71.0, 38.0, 81.0)
16 (8000.0, 47.0, 74.0, 25.0)
17 (9100.0, 9.0, 6.0, 85.0)
18 (3000.0, 99.0, 38.0, 11.0)
19 (3000.0, 13.0, 49.0, 36.0)
20 (5900.0, 82.0, 47.0, 21.0)
replaced 500.0
21 (4800.0, 46.0, 27.0, 86.0)
replaced 1100.0
22 (3500.0, 90.0, 88.0, 83.0)
replaced 3000.0
23 (1000.0, 78.0, 82.0, 22.0)
24 (6900.0, 94.0, 32.0, 21.0)
replaced 3000.0
25 (6000.0, 49.0, 35.0, 82.0)
replaced 3000.0
26 (8900.0, 72.0, 29.0, 88.0)
replaced 3500.0
27 (4200.0, 99.0, 100.0, 8.0)
replaced 3600.0
28 (3000.0, 5.0, 41.0, 52.0)
29 (3500.0, 9.0, 28.0, 73.0)
30 (9200.0, 41.0, 28.0, 84.0)
replaced 4200.0
31 (6400.0, 51.0, 83.0, 59.0)
replaced 4400.0
32 (1900.0, 34.0, 18.0, 32.0)
33 (9600.0, 72.0, 69.0, 34.0)
replaced 4800.0
34 (9600.0, 75.0, 55.0, 75.0)
replaced 4900.0
35 (5200.0, 47.0, 29.0, 18.0)
36 (6600.0, 64.0, 12.0, 97.0)
replaced 5800.0
37 (700.0, 15.0, 20.0, 81.0)
38 (2100.0, 88.0, 55.0, 77.0)
39 (900.0, 50.0, 49.0, 77.0)
40 (6000.0, 68.0, 33.0, 71.0)
replaced 5900.0
41 (200.0, 88.0, 93.0, 15.0)
42 (8800.0, 69.0, 97.0, 35.0)
replaced 5900.0
43 (9900.0, 83.0, 44.0, 15.0)
replaced 6000.0
44 (3800.0, 56.0, 21.0, 59.0)
45 (100.0, 93.0, 93.0, 34.0)
46 (6500.0, 98.0, 23.0, 65.0)
replaced 6000.0
47 (1400.0, 81.0, 39.0, 82.0)
48 (6500.0, 78.0, 26.0, 20.0)
replaced 6400.0
49 (4800.0, 98.0, 21.0, 70.0)
的print('replaced', old[0])
通話是沒有必要的,但它是用於測試和調試。
@TessellatingHeckler good catch –