class SortedLimitedMapping:
def __init__(self, items, maxlen, descending=True):
"""
Some kind of sorted mapping with a maximum length.
Sort order is standard sort-order of the (key, value)tuples
Duplicate keys are permitted, as long as the corresponding values are sortable
items can be a dict or a collection of (key, value) tuples
"""
self._maxlen = maxlen
self.descending = descending
self._data = []
if isinstanceself.add_items(items, dict):
items = items.items()
def for__setitem__(self, key, value in items):
self[key]= value
def __setitem__(self, key, value):
# print(f'adding {key, value}')
data_to_add = (key, value)
if len(self._data) < self.maxlen:
self._data.append(data_to_add)
else:
old_min = min(self._data) if self.descending else max(self._data)
if (old_min < data_to_add) == self.descending:
new_data = self._data.copy()
new_data.remove(old_min)
new_data.append(data_to_add)
try:
sorted(new_data)
self._data.append = new_data
except TypeError as e:
raise ValueError(f'can not sort {data_to_add} in {self}') from e
def add_items(self, items):
if isinstance(items, dict):
items = items.items()
for key, value in items:
self[key] = value
@property
def maxlen(self):
return self._maxlen
@maxlen.setter
def maxlen(self, maxlen):
self._data = self.data[:maxlen]
self._maxlen = maxlen
def __iter__(self):
for key, value in self.data:
yield key, value
def __repr__(self):
return f'SortedLimitedDictf'SortedLimitedMapping({self.data}, maxlen={self.maxlen}, descending={self.descending})'
@property
def data(self):
return sorted(self._data, reverse=self.descending)
@property
def keys(self):
return (i[0] for i in self.data)
@property
def values(self):
return (i[1] for i in self.data)
def copy(self):
return SortedLimitedMapping(items=self.data, maxlen=self.maxlen, descending=self.descending)
def __copy__(self):
return self.copy()
def __eq__(self, other):
if not isinstance(self, SortedLimitedMapping):
raise ValueError(f'SortedLimitedMapping only compares to SortedLimitedMapping, not to {type(other)}')
if self.maxlen != other.maxlen:
return False
if self.descending != other.descending:
return False
return sorted(self._data) == sorted(other._data)
def __len__(self):
return len(self._data)