#!/usr/bin/env python
[docs]class UniqueFIFO(object):
"""FIFO of unique objects. In other words, if an element already present
in the FIFO is appended to the FIFO, it is moved to the right end and
no element is removed from the FIFO. Elements are only removed when a
element not present in the FIFO is appended to the right end, and when
the number of elements in the FIFO exceeds `self.max_size`.
Parameters
----------
idx : int
Index of item to fetch
Returns
-------
object
Nth item in the |UniqueFIFO|
Attributes
----------
max_size : int
Maximum size of |UniqueFIFO|
"""
def __init__(self, size):
assert size > 0
self.max_size = size
self._elements = []
def __getitem__(self, idx):
"""Fetch Nth item in the |UniqueFIFO|
Parameters
----------
idx : int
Index of item to fetch
Returns
-------
object
Nth item in the |UniqueFIFO|
"""
return self._elements[idx]
def __contains__(self, el):
"""Determine whether an element is in the |UniqueFIFO|
Parameters
----------
el : hashable object
Query object
Returns
-------
bool
`True` if `el` is in the |UniqueFIFO|, `False` otherwise
"""
return el in self._elements
def __iter__(self):
"""Iterate over elements in the |UniqueFIFO|"""
return iter(self._elements)
def __len__(self):
"""Return number of objects presently in the |UniqueFIFO|
Returns
-------
int
Number of elements presently in the |UniqueFIFO|, must be less than
or equal to `self.max_size`
"""
return len(self._elements)
[docs] def append(self, el):
"""Append an item to the |UniqueFIFO|. If the item is already present
in the |UniqueFIFO|, it is moved to the right end of the FIFO, and the
length of the |UniqueFIFO| is unchanged. Otherwise, the element is
appended to the right end. If the length of the |UniqueFIFO| then
exceeds `self.max_size`, the fist element is popped.
Parameters
----------
el : hashable
Any hashable object
"""
if el in self:
# move to front if present
n = self._elements.index(el)
self._elements = self._elements[:n] + self._elements[n + 1:] + [el]
else:
# otherwise append, removing first element
# if we are too long
if len(self._elements) >= self.max_size:
self._elements = self._elements[1:]
self._elements.append(el)
else:
self._elements.append(el)
def __str__(self):
return str(self._elements)
def __repr__(self):
return "<UniqueFifo %s>" % repr(self._elements)