[英]Value-sorted dict for Python?
我對Python的dict
實現很感興趣,它為排序值提供了一個迭代接口。 即,帶有“ sortedvalues()
”函數的dict
。
天真的人可以做sorted(dict.values())
但這不是我想要的。 每次插入或刪除項目時,都必須運行完全排序,這是無效的。
請注意,我也沒有詢問關鍵字排序的字典(對於那個問題, 在Python和Python 2.6 TreeMap / SortedDictionary中的Key-ordered dict中有很好的答案? )。
一種解決方案是編寫一個繼承自dict
的類,但也維護一個按其值( sorted_keys
)排序的鍵列表,以及相應(排序)值列表( sorted_values
)。
然后,您可以定義一個使用bisect
模塊的__setitem__()
方法,以便快速了解應在兩個列表中插入新(鍵,值)對的位置k
。 然后,您可以在字典本身和您維護的兩個列表中插入新密鑰和新值,並使用sorted_values[k:k] = [new_value]
和sorted_keys[k:k] = [new_key]
; 遺憾的是,這種插入的時間復雜度是O(n)
(因此整個字典的O(n^2)
)。
有序元素插入的另一種方法是使用heapq
模塊並在其中插入(value, key)
對。 這適用於O(log n)
而不是前一段的基於列表的方法。
然后,迭代字典可以通過迭代您維護的鍵列表( sorted_keys
)來完成。
這種方法可以節省您每次要對字典進行迭代(具有排序值)時對鍵進行排序所需的時間,通過基本上將這個時間成本轉移(並且不幸地增加)來構造排序的鍵列表和值。
問題是您需要按鍵對其進行排序或散列以獲得合理的插入和查找性能。 實現它的一種天真的方式是條目的值排序樹結構,以及查找鍵的樹位置的字典。 您需要深入更新樹,因為這個查找字典需要保持正確。 基本上,就像你可以為可更新堆做的那樣。
我認為有太多的選擇可以從這樣的結構中制作出一個合理的標准庫選項,而它卻很少需要。
更新 :可能適合您的技巧是使用雙重結構:
像往常一樣存儲鍵值對的常規dict
任何類型的排序列表,例如使用bisect
然后,您必須在兩者上實現常見操作:將新值插入到兩個結構中。 棘手的部分是更新和刪除操作。 您使用第一個結構查找舊值,從第二個結構中刪除舊值,然后(更新時)像以前一樣重新插入。
如果您還需要知道密鑰,請在b列表中存儲(值,密鑰)對。
更新2 :嘗試這個類:
import bisect
class dictvs(dict):
def __init__(self):
self._list = []
def __setitem__(self, key, value):
old = self.get(key)
if old is None:
bisect.insort(self._list, value)
dict.__setitem__(self, key, value)
else:
oldpos = bisect.bisect_left(self._list, old)
newpos = bisect.bisect_left(self._list, value)
if newpos > oldpos:
newpos -= 1
for i in xrange(oldpos, newpos):
self._list[i] = self._list[i + 1]
else:
for i in xrange(oldpos, newpos, -1):
self._list[i] = self._list[i - 1]
self._list[newpos] = value
dict.__setitem__(self, key, value)
def __delitem__(self, key):
old = self.get(key)
if old is not None:
oldpos = bisect.bisect(self._list, old)
del self._list[oldpos]
dict.__delitem__(self, key)
def values(self):
return list(self._list)
我想這不是一個完整的dict
。 我沒有測試刪除,只是一個小的更新集。 你應該對它進行更大的單元測試,並將values()
的返回values()
與sorted(dict.values(instance))
的返回values()
進行比較。 這只是為了說明如何使用bisect
更新排序列表
這是另一個更簡單的想法:
dict
的類。 在評論中提到幾乎排序的排序列表很快,所以這種方法應該非常快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.