繁体   English   中英

根据值从列表中删除namedtuple

[英]Remove namedtuple from list based on value

考虑下面的类,该类扩展了list并追加了orderedtuple

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

您可以向类中添加一个索引,以跟踪地图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]]
[namedtuple for namedtuple in list if namedtuple.id != '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

该解决方案的主要优点是简单。 您可以在不更改类定义的任何其他部分的情况下实现remove方法。 也就是说,它仍然以O(n)复杂度运行。 如果性能是您主要关注的问题,那么您应该花时间实现@MartijnPieters提出的O(1) id-lookup方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM