如何在尺寸有限的结构中保存有序的独特物品?
How to keep ordered unique items in a size limited structure?
我需要将元素流保存在一个大小有限的列表中。流中可能有重复的元素,但我只需要保留唯一的元素。此外,当我的列表的大小超过指定限制时,我需要删除最旧的元素并添加新元素。
我已经尝试过 set
和 list
。 set
的问题是它没有大小限制,如果我想删除最旧的元素,我不知道如何检索它,因为 set 是无序的;但是,它解决了唯一性问题。
另一方面,list
保持项目的顺序,但每当我想插入一个新元素时,我都需要检查可能的重复项,这会花费很多时间。 list
和 set
.
一样不受大小限制
我的第三个选择可能是collections.deque
,但我不知道它是否保持订单。有没有办法让 collections.deque
中的项目保持唯一性?
这些是我的代码示例 list
:
ids = list()
for item in stream:
if item not in ids:
ids.append(item)
if len(ids) >= len_limit:
del ids[0]
和set
:
ids = set()
for item in stream:
ids.add(item)
if len(ids) >= len_limit:
ids.remove(list(ids)[0])
您可以编写自己的 class 来保留 deque 和 set:
import collections
class Structure:
def __init__(self, size):
self.deque = collections.deque(maxlen=size)
self.set = set()
def append(self, value):
if value not in self.set:
if len(self.deque) == self.deque.maxlen:
discard = self.deque.popleft()
self.set.discard(discard)
self.deque.append(value)
self.set.add(value)
s = Structure(2)
s.append(1)
s.append(2)
s.append(3)
s.append(3)
print(s.deque) # deque([2, 3], maxlen=2)
我创建了一个带有列表的简单队列。我还以这样一种方式安排了条件,即比较次数较少
class Queue:
def __init__(self,size):
self.elements = []
self.max_size = size
def put(self,elem):
if(elem in self.elements):
return
elif(len(self.elements) < self.max_size):
self.elements.append(elem)
else:
self.elements = self.elements[1:]+[elem]
def __str__(self):
return self.elements.__str__()
q=Queue(3)
q.put(1)
print(q)
q.put(2)
print(q)
q.put(2)
print(q)
q.put(3)
print(q)
q.put(3)
print(q)
q.put(4)
print(q)
您可能想研究使用 orderedset
包。它可以通过 pip 或 conda 获得。它是一个非常快速的 Cpython 库,实现了有序集。
pip install orderedset
或
conda install orderedset -c conda-forge
您可以子类化 OrderedSet
以创建具有最大元素数的对象。
from orderedset import OrderedSet
class DequeSet(OrderedSet):
def __init__(self, *args, maxlen=0, **kwargs):
if not isinstance(maxlen, int):
raise TypeError('`maxlen` must be an integer.')
if not maxlen>=0:
raise ValueError('`maxlen` must not be negative.')
self._maxlen = maxlen
if maxlen:
args = (args[0][-maxlen:],)
super().__init__(*args, **kwargs)
@property
def maxlen(self):
return self._maxlen
def _checkpop(self):
if not self._maxlen:
return
while self.__len__() > self._maxlen:
self.pop(last=False)
def __getattr__(self, attr):
self._checkpop()
return getattr(self, attr)
# this will truncate to the last 3 elements
ds = DequeSet('abcd', maxlen=3)
ds
3 returns:
DequeSet(['b', 'c', 'd'])
ds.add('e')
ds
# returns:
DequeSet(['c', 'd', 'e'])
我需要将元素流保存在一个大小有限的列表中。流中可能有重复的元素,但我只需要保留唯一的元素。此外,当我的列表的大小超过指定限制时,我需要删除最旧的元素并添加新元素。
我已经尝试过 set
和 list
。 set
的问题是它没有大小限制,如果我想删除最旧的元素,我不知道如何检索它,因为 set 是无序的;但是,它解决了唯一性问题。
另一方面,list
保持项目的顺序,但每当我想插入一个新元素时,我都需要检查可能的重复项,这会花费很多时间。 list
和 set
.
我的第三个选择可能是collections.deque
,但我不知道它是否保持订单。有没有办法让 collections.deque
中的项目保持唯一性?
这些是我的代码示例 list
:
ids = list()
for item in stream:
if item not in ids:
ids.append(item)
if len(ids) >= len_limit:
del ids[0]
和set
:
ids = set()
for item in stream:
ids.add(item)
if len(ids) >= len_limit:
ids.remove(list(ids)[0])
您可以编写自己的 class 来保留 deque 和 set:
import collections
class Structure:
def __init__(self, size):
self.deque = collections.deque(maxlen=size)
self.set = set()
def append(self, value):
if value not in self.set:
if len(self.deque) == self.deque.maxlen:
discard = self.deque.popleft()
self.set.discard(discard)
self.deque.append(value)
self.set.add(value)
s = Structure(2)
s.append(1)
s.append(2)
s.append(3)
s.append(3)
print(s.deque) # deque([2, 3], maxlen=2)
我创建了一个带有列表的简单队列。我还以这样一种方式安排了条件,即比较次数较少
class Queue:
def __init__(self,size):
self.elements = []
self.max_size = size
def put(self,elem):
if(elem in self.elements):
return
elif(len(self.elements) < self.max_size):
self.elements.append(elem)
else:
self.elements = self.elements[1:]+[elem]
def __str__(self):
return self.elements.__str__()
q=Queue(3)
q.put(1)
print(q)
q.put(2)
print(q)
q.put(2)
print(q)
q.put(3)
print(q)
q.put(3)
print(q)
q.put(4)
print(q)
您可能想研究使用 orderedset
包。它可以通过 pip 或 conda 获得。它是一个非常快速的 Cpython 库,实现了有序集。
pip install orderedset
或
conda install orderedset -c conda-forge
您可以子类化 OrderedSet
以创建具有最大元素数的对象。
from orderedset import OrderedSet
class DequeSet(OrderedSet):
def __init__(self, *args, maxlen=0, **kwargs):
if not isinstance(maxlen, int):
raise TypeError('`maxlen` must be an integer.')
if not maxlen>=0:
raise ValueError('`maxlen` must not be negative.')
self._maxlen = maxlen
if maxlen:
args = (args[0][-maxlen:],)
super().__init__(*args, **kwargs)
@property
def maxlen(self):
return self._maxlen
def _checkpop(self):
if not self._maxlen:
return
while self.__len__() > self._maxlen:
self.pop(last=False)
def __getattr__(self, attr):
self._checkpop()
return getattr(self, attr)
# this will truncate to the last 3 elements
ds = DequeSet('abcd', maxlen=3)
ds
3 returns:
DequeSet(['b', 'c', 'd'])
ds.add('e')
ds
# returns:
DequeSet(['c', 'd', 'e'])