根据值从列表中删除 namedtuple
Remove namedtuple from list based on value
考虑以下扩展 list
并附加 orderedtuple
的 class:
from collections import namedtuple
Order = namedtuple('Order', ['id', 'value'])
class Orders(list):
def __init__(self, *args):
super(Orders, self).__init__()
self.extend(args)
def add(self, id, value):
self.append(Order(id, value))
...添加一些元素...
order = Orders()
order.add(1, 'alpha')
order.add(2, 'beta')
order.add(3, 'lambda')
order.add(4, 'omega')
...我们还剩下...
print order
[Order(id=1, value='alpha'), Order(id=2, value='beta'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
假设我想通过 id
删除任意元素。例如:
order.remove(id=2) # ideal function call to remove by `id`
print order
[Order(id=1, value='alpha'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
是否有相当简单的方法来完成此操作?
你可以慢慢来:
def remove(self, id=None, value=None):
for elem in self:
if (id is not None and elem.id == id or
value is not None and elem.value == value):
super(Orders, self).remove(elem)
break
您可以向您的 class 添加一个索引,用于跟踪特定索引的地图 ID 和/或值,但您需要在操作包含的列表时保持该索引为最新命令。它看起来像这样:
def __init__(self, *args):
# ...
self._ids = {}
def append(self, id, value):
if id in ids:
raise ValueError('This order already exists!')
super(Orders, self).append(Order(id, value))
self._ids[id] = len(self) - 1
并且,如果您还调整了所有其他可以改变列表和更改顺序等的方法,您就可以通过它们的 id 快速找到订单:
def remove(self, id):
if id not in self._ids
raise ValueError('No such order exists!')
del self[self._ids[id]]
您可以构建自定义 remove
方法来为您执行此操作:
def remove(self, id):
for index, item in enumerate(self):
if item.id == id:
break
else:
raise ValueError("id not found")
del self[index]
演示:
>>> class Orders(list):
... def __init__(self, *args):
... super(Orders, self).__init__()
... self.extend(args)
... def add(self, id, value):
... self.append(Order(id, value))
... def remove(self, id):
... for index, item in enumerate(self):
... if item.id == id:
... break
... else:
... raise ValueError("id not found")
... del self[index]
...
>>> order = Orders()
>>> order.add(1, 'alpha')
>>> order.add(2, 'beta')
>>> order.add(3, 'lambda')
>>> order.add(4, 'omega')
>>> order
[Order(id=1, value='alpha'), Order(id=2, value='beta'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
>>> order.remove(2)
>>> order
[Order(id=1, value='alpha'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
>>> order.remove(5) # Nonexistent id
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in remove
ValueError: id not found
>>>
请注意,该函数只传递一次数据,就像正常的 list.remove
一样。
此解决方案的主要优点是简单。您可以在不更改 class 定义的任何其他部分的情况下实现 remove
方法。也就是说,它仍然以 O(n)
复杂度运行。如果性能是您的主要关注点,那么您应该花时间实施@MartijnPieters 提出的 O(1)
id-lookup 方法。
[namedtuple for namedtuple in list if namedtuple.id != 'id']
考虑以下扩展 list
并附加 orderedtuple
的 class:
from collections import namedtuple
Order = namedtuple('Order', ['id', 'value'])
class Orders(list):
def __init__(self, *args):
super(Orders, self).__init__()
self.extend(args)
def add(self, id, value):
self.append(Order(id, value))
...添加一些元素...
order = Orders()
order.add(1, 'alpha')
order.add(2, 'beta')
order.add(3, 'lambda')
order.add(4, 'omega')
...我们还剩下...
print order
[Order(id=1, value='alpha'), Order(id=2, value='beta'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
假设我想通过 id
删除任意元素。例如:
order.remove(id=2) # ideal function call to remove by `id`
print order
[Order(id=1, value='alpha'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
是否有相当简单的方法来完成此操作?
你可以慢慢来:
def remove(self, id=None, value=None):
for elem in self:
if (id is not None and elem.id == id or
value is not None and elem.value == value):
super(Orders, self).remove(elem)
break
您可以向您的 class 添加一个索引,用于跟踪特定索引的地图 ID 和/或值,但您需要在操作包含的列表时保持该索引为最新命令。它看起来像这样:
def __init__(self, *args):
# ...
self._ids = {}
def append(self, id, value):
if id in ids:
raise ValueError('This order already exists!')
super(Orders, self).append(Order(id, value))
self._ids[id] = len(self) - 1
并且,如果您还调整了所有其他可以改变列表和更改顺序等的方法,您就可以通过它们的 id 快速找到订单:
def remove(self, id):
if id not in self._ids
raise ValueError('No such order exists!')
del self[self._ids[id]]
您可以构建自定义 remove
方法来为您执行此操作:
def remove(self, id):
for index, item in enumerate(self):
if item.id == id:
break
else:
raise ValueError("id not found")
del self[index]
演示:
>>> class Orders(list):
... def __init__(self, *args):
... super(Orders, self).__init__()
... self.extend(args)
... def add(self, id, value):
... self.append(Order(id, value))
... def remove(self, id):
... for index, item in enumerate(self):
... if item.id == id:
... break
... else:
... raise ValueError("id not found")
... del self[index]
...
>>> order = Orders()
>>> order.add(1, 'alpha')
>>> order.add(2, 'beta')
>>> order.add(3, 'lambda')
>>> order.add(4, 'omega')
>>> order
[Order(id=1, value='alpha'), Order(id=2, value='beta'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
>>> order.remove(2)
>>> order
[Order(id=1, value='alpha'), Order(id=3, value='lambda'), Order(id=4, value='omega')]
>>> order.remove(5) # Nonexistent id
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 12, in remove
ValueError: id not found
>>>
请注意,该函数只传递一次数据,就像正常的 list.remove
一样。
此解决方案的主要优点是简单。您可以在不更改 class 定义的任何其他部分的情况下实现 remove
方法。也就是说,它仍然以 O(n)
复杂度运行。如果性能是您的主要关注点,那么您应该花时间实施@MartijnPieters 提出的 O(1)
id-lookup 方法。
[namedtuple for namedtuple in list if namedtuple.id != 'id']