Как построить хранилище отмены с ограничением? - PullRequest
1 голос
/ 02 августа 2010

Я хочу создать структуру данных для хранения ограниченного буфера отмены, например, хранить данные 6 dict с псевдокодом ниже:

rawdict1 = {1}
buffer = [{1}]

rawdict1 = {2}
buffer = [{2}{1}]      # {1} stored on the postion

rawdict1 = {3}
buffer = [{3}{2}{1}]      
...
rawdict1 = {5}
buffer = [{5}{4}{3}{2}{1}]      # max length limited to 5

rawdict1 = {6}
buffer = [{6}{5}{4}{3}{2}]      # {1} has been deleted because exceed the limit

when I want to restore the rawdict1 later, I can use something looks like:

rawdict1 = buffer[5]                 # restore the 5th dict.

Мой вопрос: может ли существующий тип данных встроенного или стандартного типа библиотеки бытьиспользуется для такой цели?

И возможно ли, чтобы такая структура могла хранить мультитипы в одном экземпляре структуры, скажем, если я хочу хранить dict и самоопределяемый класс за один раз?

Спасибо!

Rgs,

KC

Ответы [ 5 ]

2 голосов
/ 02 августа 2010

Возможно использовать что-то вроде этого:

import collections

class UndoBuffer(object):
    def __init__(self,value,max_length=5):
        self.max_length=max_length
        self._buffer=collections.deque([value],max_length)
    @property
    def data(self):
        return self._buffer[-1]
    @data.setter
    def data(self,value):
        self._buffer.append(value)
    def restore(self,index):
        self.data=self._buffer[index]

Создать объект UndoBuffer

rawdict=UndoBuffer('{1}')      

Установка атрибута data автоматически сохраняет значение в _buffer:

print(rawdict._buffer)
# deque(['{1}'], maxlen=5)
print(rawdict.data)
# {1}

При изменении значения rawdict.data добавляется значение к rawdict._buffer:

rawdict.data = '{2}'
print(rawdict._buffer)
# deque(['{1}', '{2}'], maxlen=5)

Buf, если вы открываете rawdict.data, вы просто получаете самое последнее значение:

print(rawdict.data)
# {2}

Измените значение еще несколько раз.«{1}» удаляется, когда буфер заполнен до максимальной длины:

rawdict.data = '{3}'
rawdict.data = '{4}'
rawdict.data = '{5}'
print(rawdict._buffer)
# deque(['{1}', '{2}', '{3}', '{4}', '{5}'], maxlen=5)
rawdict.data = '{6}'
print(rawdict._buffer)
# deque(['{2}', '{3}', '{4}', '{5}', '{6}'], maxlen=5)

Восстановление значения из rawdict._buffer:

rawdict.restore(0)   # set rawdict.data to rawdict._buffer[0]
print(rawdict.data)
# {2}
print(rawdict._buffer)
# deque(['{3}', '{4}', '{5}', '{6}', '{2}'], maxlen=5)
1 голос
/ 02 августа 2010

Модуль коллекций, начиная с python 2.6, содержит коллекцию deque. Он ведет себя так, как вам нужно:

>>> import collections
>>> buffer = collections.deque([],6)
>>> buffer.extend(range(6))
>>> buffer
deque([0, 1, 2, 3, 4, 5], maxlen=6)
>>> buffer.append(6)
>>> buffer
deque([1, 2, 3, 4, 5, 6], maxlen=6)
>>> buffer[-1]
6
1 голос
/ 02 августа 2010

Вы можете быстро создать подкласс списка, чтобы разрешить только ограниченное хранилище.

class LimitedStack(list):
 def __init__(self,limit=6):
    list.__init__(self)
    self.limit = limit

 def append(self,obj):
    if len(self) == self.limit:
        list.pop(self,0)
    list.append(self,obj)

Списки Python не обязательно должны быть определенного типа, как общие списки в C #.Они будут хранить любой объект, к которому вы добавляете.

1 голос
/ 02 августа 2010

Вы не можете сделать это для голого имени (например, rawdict1), потому что у вас нет возможности перехватить назначения для голого имени и заставить их делать это когда-то «на стороне», например, сохраняя предыдущее значение.Это легко сделать на украшенном имени, например:

undoable.rawdict1 = {1}

и т. П., Сделав undoable экземпляром класса с соответствующим __setitem__, к которому добавляется предыдущийзначение (если оно есть) в список, и выводит 0-й элемент, если список становится слишком длинным.Но этого будет недостаточно для других «отменяемых» действий, помимо назначения, таких как undoable.rawdict1.update(whatever) - вы уверены, что вам это не нужно?

0 голосов
/ 02 августа 2010

CSLA.NET Framework Rockford Lhotka содержит архитектуру отмены.Возможно, вы могли бы изучить это и выяснить, что он сделал, или даже использовать это из коробки.

...