Python 以特定大小顺序覆盖字典
Python overwrite a dictionary sequentially at certain size
我有一个不断向字典添加数据的脚本(无法更改意味着没有列表或停止添加数据)。它可以轻松触及其中的 1000 多个不同的键。
我需要每个键和值,但不想重置字典 foo
。
foo = {"369610": "a", "109122": "a", "907897": "a", "333291":"a", "381819": "a", "387583": "a", "677430": "a", "660221": "a", "118095":"a", "612172": "a"}
print(len(foo)) # At 10
foo["223533"] = "a" # Replaces 369610 in the dictionary
foo["601336"] = "a" # Replaces 109122 in the dictionary
print(len(foo)) # Should be 10
如果我要向字典添加更多键,它将替换 907897 然后 333291 然后 381819 然后 387583。一旦达到 10 的限制,再添加将替换第一个索引 223533。我仍然想访问每个键的每个值关于为什么这是字典而不是列表。
我想遍历字典,然后获取每个条目并用以下内容覆盖该条目:
del foo[index]
foo[random.randint(5000,100000)] = "a"
但我觉得这是一个低效的解决方案。
好吧,如果有人来这里寻找不允许重写键或删除键(仅插入和查找)的字典,那么这就是我的解决方案:
class CircularBuffer:
def __init__(self, size):
self.maxsize = size
self.array = [None] * size
self.ptr = 0
self.get_ordered = self.GOpartial
self.add = self.ADDpartial
self.len = self.LENpartial
def __getitem__(self, item):
return self.array[item]
def LENpartial(self):
return self.ptr
def LENfull(self):
return self.maxsize
def ADDpartial(self, item):
self.array[self.ptr] = item
self.ptr = self.ptr + 1
if self.ptr == self.maxsize:
self.add = self.ADDfull
self.get_ordered = self.GOfull
self.len = self.LENfull
self.ptr = 0
return None
def ADDfull(self, item):
ret = self.array[self.ptr]
self.array[self.ptr] = item
self.ptr = (self.ptr + 1) % self.maxsize
return ret
def GOpartial(self):
return self.array[:self.ptr]
def GOfull(self):
return self.array[self.ptr:] + self.array[0: self.ptr]
def __repr__(self):
return self.array.__repr__()
def __len__(self):
return self.len()
class CircularBufferDict:
def __init__(self, size):
self.keys = CircularBuffer(size)
self.mapping = {}
def add(self, k, v):
if k in self.mapping:
raise KeyError(f"Key {k} already exists in the dictionary.")
rewritten = self.keys.add(k)
if rewritten is not None:
del self.mapping[rewritten]
self.mapping[k] = v
def get(self, k):
return self.mapping[k]
达到最大尺寸后,它保持恒定数量的元素。每个操作时间属于 O(1)
(在哈希查找时摊销)。使用此结构时,删除(并因此覆盖)效率低下(对数组进行碎片整理需要线性时间)。
from collections import OrderedDict
class FooDict(OrderedDict):
def __init__(self, maxsize=5, /, *args, **kwds):
self.maxsize = maxsize
super().__init__(*args, **kwds)
def __getitem__(self, key):
value = super().__getitem__(key)
return value
def __setitem__(self, key, value):
super().__setitem__(key, value)
if len(self) > self.maxsize:
oldest = next(iter(self))
del self[oldest]
foo = FooDict()
for i in range(10):
foo[random.randint(5000,100000)] = "a"
print(foo)
FooDict([(82596, 'a')])
FooDict([(82596, 'a'), (67860, 'a')])
FooDict([(82596, 'a'), (67860, 'a'), (13232, 'a')])
FooDict([(82596, 'a'), (67860, 'a'), (13232, 'a'), (45835, 'a')])
FooDict([(82596, 'a'), (67860, 'a'), (13232, 'a'), (45835, 'a'), (15591, 'a')])
FooDict([(67860, 'a'), (13232, 'a'), (45835, 'a'), (15591, 'a'), (36689, 'a')])
FooDict([(13232, 'a'), (45835, 'a'), (15591, 'a'), (36689, 'a'), (60175, 'a')])
FooDict([(45835, 'a'), (15591, 'a'), (36689, 'a'), (60175, 'a'), (87882, 'a')])
FooDict([(15591, 'a'), (36689, 'a'), (60175, 'a'), (87882, 'a'), (59414, 'a')])
FooDict([(36689, 'a'), (60175, 'a'), (87882, 'a'), (59414, 'a'), (87218, 'a')])
我有一个不断向字典添加数据的脚本(无法更改意味着没有列表或停止添加数据)。它可以轻松触及其中的 1000 多个不同的键。
我需要每个键和值,但不想重置字典 foo
。
foo = {"369610": "a", "109122": "a", "907897": "a", "333291":"a", "381819": "a", "387583": "a", "677430": "a", "660221": "a", "118095":"a", "612172": "a"}
print(len(foo)) # At 10
foo["223533"] = "a" # Replaces 369610 in the dictionary
foo["601336"] = "a" # Replaces 109122 in the dictionary
print(len(foo)) # Should be 10
如果我要向字典添加更多键,它将替换 907897 然后 333291 然后 381819 然后 387583。一旦达到 10 的限制,再添加将替换第一个索引 223533。我仍然想访问每个键的每个值关于为什么这是字典而不是列表。
我想遍历字典,然后获取每个条目并用以下内容覆盖该条目:
del foo[index]
foo[random.randint(5000,100000)] = "a"
但我觉得这是一个低效的解决方案。
好吧,如果有人来这里寻找不允许重写键或删除键(仅插入和查找)的字典,那么这就是我的解决方案:
class CircularBuffer:
def __init__(self, size):
self.maxsize = size
self.array = [None] * size
self.ptr = 0
self.get_ordered = self.GOpartial
self.add = self.ADDpartial
self.len = self.LENpartial
def __getitem__(self, item):
return self.array[item]
def LENpartial(self):
return self.ptr
def LENfull(self):
return self.maxsize
def ADDpartial(self, item):
self.array[self.ptr] = item
self.ptr = self.ptr + 1
if self.ptr == self.maxsize:
self.add = self.ADDfull
self.get_ordered = self.GOfull
self.len = self.LENfull
self.ptr = 0
return None
def ADDfull(self, item):
ret = self.array[self.ptr]
self.array[self.ptr] = item
self.ptr = (self.ptr + 1) % self.maxsize
return ret
def GOpartial(self):
return self.array[:self.ptr]
def GOfull(self):
return self.array[self.ptr:] + self.array[0: self.ptr]
def __repr__(self):
return self.array.__repr__()
def __len__(self):
return self.len()
class CircularBufferDict:
def __init__(self, size):
self.keys = CircularBuffer(size)
self.mapping = {}
def add(self, k, v):
if k in self.mapping:
raise KeyError(f"Key {k} already exists in the dictionary.")
rewritten = self.keys.add(k)
if rewritten is not None:
del self.mapping[rewritten]
self.mapping[k] = v
def get(self, k):
return self.mapping[k]
达到最大尺寸后,它保持恒定数量的元素。每个操作时间属于 O(1)
(在哈希查找时摊销)。使用此结构时,删除(并因此覆盖)效率低下(对数组进行碎片整理需要线性时间)。
from collections import OrderedDict
class FooDict(OrderedDict):
def __init__(self, maxsize=5, /, *args, **kwds):
self.maxsize = maxsize
super().__init__(*args, **kwds)
def __getitem__(self, key):
value = super().__getitem__(key)
return value
def __setitem__(self, key, value):
super().__setitem__(key, value)
if len(self) > self.maxsize:
oldest = next(iter(self))
del self[oldest]
foo = FooDict()
for i in range(10):
foo[random.randint(5000,100000)] = "a"
print(foo)
FooDict([(82596, 'a')])
FooDict([(82596, 'a'), (67860, 'a')])
FooDict([(82596, 'a'), (67860, 'a'), (13232, 'a')])
FooDict([(82596, 'a'), (67860, 'a'), (13232, 'a'), (45835, 'a')])
FooDict([(82596, 'a'), (67860, 'a'), (13232, 'a'), (45835, 'a'), (15591, 'a')])
FooDict([(67860, 'a'), (13232, 'a'), (45835, 'a'), (15591, 'a'), (36689, 'a')])
FooDict([(13232, 'a'), (45835, 'a'), (15591, 'a'), (36689, 'a'), (60175, 'a')])
FooDict([(45835, 'a'), (15591, 'a'), (36689, 'a'), (60175, 'a'), (87882, 'a')])
FooDict([(15591, 'a'), (36689, 'a'), (60175, 'a'), (87882, 'a'), (59414, 'a')])
FooDict([(36689, 'a'), (60175, 'a'), (87882, 'a'), (59414, 'a'), (87218, 'a')])