活跃农民
- 积分
- 525
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2019-2-16
- 最后登录
- 1970-1-1
|
我的想法是用一个Dictionary of List,每次同时存取当前Snapshot ID和存取值,Get就直接拿尾端的值,Get with Snapshot ID 就用哈希后用二分法查询,这样内存只会存取需要改变的值,Get, Put 都是O(1),只是Snapshot ID 查找需要Log(该值的版本修改数),如有更好的请多指教
- class VersionDict:
- def __init__(self):
- self.version = 0
- self.map = defaultdict(list)
-
- def _bsearch(self, arr, condition):
- left, right = 0, len(arr)
- while left < right:
- mid = (left + right) // 2
- if condition(arr[mid]):
- right = mid
- else:
- left = mid + 1
- return left
- def get(self, key):
- if not self.map[key]:
- return None
- return self.map[key][-1][1]
- def get_with_version(self, key, version):
- if not self.map[key] or version > self.version:
- return None
- ind = self._bsearch(self.map[key], lambda ele : ele[0] > version)
- if ind == 0:
- return None
- return self.map[key][ind-1][1]
- def put(self, key, value):
- if not self.map[key] or self.map[key][-1][0] < self.version:
- self.map[key].append([self.version, value])
- else:
- self.map[key][-1][1] = value
- def take_snapshot(self):
- self.version += 1
- return self.version - 1
- class TestVersionDict(unittest.TestCase):
- def test_basics(self):
- vdict = VersionDict()
- vdict.put("a", "foo")
- vdict.put("b", "bar")
- assert vdict.get("a") == "foo"
- assert vdict.get("b") == "bar"
- assert vdict.get("c") is None
- vdict.put("a", "duplicate")
- assert vdict.get("a") == "duplicate"
- assert vdict.get("b") == "bar"
- assert vdict.get("c") is None
- snapshot_id_1 = vdict.take_snapshot()
- vdict.put("b", "hello")
- vdict.put("c", "world")
- assert vdict.get("b") == "hello"
- assert vdict.get_with_version("b", snapshot_id_1) == "bar"
- assert vdict.get("a") == "duplicate"
- assert vdict.get_with_version("a", snapshot_id_1) == "duplicate"
- assert vdict.get("c") == "world"
- assert vdict.get_with_version("c", snapshot_id_1) is None
- assert vdict.get("d") is None
- assert vdict.get_with_version("d", snapshot_id_1) is None
- snapshot_id_2 = vdict.take_snapshot()
- vdict.put("b", "new")
- assert vdict.get("a") == "duplicate"
- assert vdict.get_with_version("a", snapshot_id_1) == "duplicate"
- assert vdict.get_with_version("a", snapshot_id_2) == "duplicate"
- assert vdict.get("b") == "new"
- assert vdict.get_with_version("b", snapshot_id_1) == "bar"
- assert vdict.get_with_version("b", snapshot_id_2) == "hello"
- assert vdict.get("c") == "world"
- assert vdict.get_with_version("c", snapshot_id_1) is None
- assert vdict.get_with_version("c", snapshot_id_2) == "world"
- assert vdict.get("d") is None
- assert vdict.get_with_version("d", snapshot_id_1) is None
- assert vdict.get_with_version("d", snapshot_id_2) is None
复制代码 |
|