Я полностью согласен с идеей использования ограниченной длины Python deque
, если она доступна, а если нет, простое решение Майкла Андерсона вполне адекватно.(Я проголосовал за оба) Но я просто хотел упомянуть третий вариант кольцевого буфера, который часто используется для такого рода задач, когда важны низкий объем памяти и высокая скорость выполнения.(Другими словами, в ситуациях, когда вы, вероятно, не будете использовать Python :-p) Например, ядро Linux использует эту структуру для хранения сообщений журнала, сгенерированных во время процесса загрузки, до запуска системного регистратора.
Реализация Python может выглядеть так:
class RingBuffer(object):
def __init__(self, n):
self._buf = [None] * n
self._index = 0
self._valid = 0
def add(self, obj):
n = len(self._buf)
self._buf[self._index] = obj
self._index += 1
if self._index == n
self._index = 0
if self._valid < n:
self._valid += 1
def __len__(self):
return self._valid
# could include other methods for accessing or modifying the contents
В основном, это то, что он предварительно выделяет массив (в Python, список) желаемой длины и заполняет его фиктивными значениями.Буфер также содержит «индекс», который указывает на следующую точку в списке, которая должна быть заполнена значением.Каждый раз, когда значение добавляется, оно сохраняется в этом месте и индекс увеличивается.Когда индекс достигает длины массива, он возвращается к нулю.Вот пример (я использую 0
вместо None
для фиктивного значения только потому, что его быстрее набирать):
[0,0,0,0,0]
^
# add 1
[1,0,0,0,0]
^
# add 2
[1,2,0,0,0]
^
# add 3
[1,2,3,0,0]
^
# add 4
[1,2,3,4,0]
^
# add 5
[1,2,3,4,5]
^
# add 6
[6,2,3,4,5]
^
# add 7
[6,7,3,4,5]
^
и т. Д.