只有一个字典,从键映射到(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