只有一個字典,從鍵映射到(revision_number,actual_value)元組列表。當前值爲the_dict[akey][-1][1]
。回滾僅涉及從每個列表的末尾彈出適當的條目。
更新:回滾的例子
KEY1 - > [(10, 'v1-10'),(20, 'v1-20')]
方案1:當前修訂爲30 ,回滾到25:什麼也沒發生
場景2:當前30,回15:彈出最後一個條目
方案3:目前的30,回到5:彈出兩個條目
更新2:快回退(與取捨)
我覺得你對每一個彈出列表關心的是更好的表述爲「需要檢查每一個清單,看看是否需要啪」。隨着更奇特的數據結構(更多的內存,更多的時間來維護添加和更新操作中的花哨位),您可以減少回滾的時間。
添加一個數組(由修訂號索引),其值是在該修訂中更改的字典值的列表。
# Original rollback code:
for rlist in the_dict.itervalues():
if not rlist: continue
while rlist[-1][0] > target_revno:
rlist.pop()
# New rollback code
for revno in xrange(current_revno, target_revno, -1):
for rlist in delta_index[revno]:
assert rlist[-1][0] == revno
del rlist[-1] # faster than rlist.pop()
del delta_index[target_revno+1:]
更新3:票友方法
import collections
class RevDict(collections.MutableMapping):
def __init__(self):
self.current_revno = 0
self.dict = {}
self.delta_index = [[]]
def __setitem__(self, key, value):
if key in self.dict:
rlist = self.dict[key]
last_revno = rlist[-1][0]
rtup = (self.current_revno, value)
if last_revno == self.current_revno:
rlist[-1] = rtup
# delta_index already has an entry for this rlist
else:
rlist.append(rtup)
self.delta_index[self.current_revno].append(rlist)
else:
rlist = [(self.current_revno, value)]
self.dict[key] = rlist
self.delta_index[self.current_revno].append(rlist)
def __getitem__(self, key):
if not key in self.dict:
raise KeyError(key)
return self.dict[key][-1][1]
def new_revision(self):
self.current_revno += 1
self.delta_index.append([])
def roll_back(self, target_revno):
assert 0 <= target_revno < self.current_revno
for revno in xrange(self.current_revno, target_revno, -1):
for rlist in self.delta_index[revno]:
assert rlist[-1][0] == revno
del rlist[-1]
del self.delta_index[target_revno+1:]
self.current_revno = target_revno
def __delitem__(self, key):
raise TypeError("RevDict doesn't do del")
def keys(self):
return self.dict.keys()
def __contains__(self, key):
return key in self.dict
def iteritems(self):
for key, rlist in self.dict.iteritems():
yield key, rlist[-1][1]
def __len__(self):
return len(self.dict)
def __iter__(self):
return self.dict.iterkeys()
我喜歡這個,因爲它的簡單性,但我擔心它可能無法很好地擴展:回滾涉及每個按鍵的彈出列表,而修改只能觸摸幾個按鍵。 – shabbychef 2010-04-15 22:37:50
對不起,但我不明白你的意見。看到我更新的答案。 – 2010-04-16 00:56:42
是的:擔心的是回滾應該是很大的 - 三角洲的O回滾,而不是鍵的總數(或更糟糕的)的幾乎-o。對於我的應用程序來說,維護修改後的密鑰的權衡可能不值得。我會發布我的版本進行比較。 – shabbychef 2010-04-16 16:27:24