【问题标题】:How to delete an object from a list inside a list?如何从列表中的列表中删除对象?
【发布时间】:2016-12-19 17:21:32
【问题描述】:

假设有三个列表,第三个是包含前两个的列表:

Friendly_List = list()
Enemy_List = list()
Battle_Space = list([Friendly_List, Enemy_List])

还有一个地精类:

class Goblin(object):
    def __init__(self):
        self.Name = "Goblin"
        self.HP = random.randint(15,20)
        self.Damage = random.randint(5,10)

我创建了一个 Goblin 类的实例:

x = Goblin()

然后放入Friendly_List:

Friendly_List.append(x)

现在假设地精英勇地死去,必须从战场上移除。如果我执行 Friendly_List.remove(x),则可以毫无问题地移除地精。

如果我执行 Battle_Space.remove(x),它表示 x 不在列表中 - 即使 x 在属于 Battle_Space 列表的列表之一中。

我想我真正想问的是:实现 Battle_Space.remove(x) 所需行为的正确方法是什么?移除一个深层的实例?

【问题讨论】:

  • 您的问题有两种可能的解释:您是想仅在特定“位置”删除x,还是在它可能出现的任何地方删除它?
  • 您必须指定要从哪个列表中删除:Battle_Space[0].remove(x)
  • 我想删除可能出现在 Battle_Space 列表中的 x。
  • @Kos 暗示Goblin 有可能同时出现在友军和敌军名单中?
  • 尝试对变量和属性使用 PEP-8 命名约定。以大写字母开头的名称表示一个类,如果它是一个变量或属性,它会混淆其他程序员。变量和属性名称全部小写,必要时加下划线。

标签: python python-3.x oop object


【解决方案1】:

简单但可能不太干净的方法是Battle_Space[0].remove(x)。您必须确保第一个列表是友好列表。

我对可读性的建议是考虑将friendly_listenemy_list 放在BattleSpace 对象中,以便您可以通过名称引用它们。您还可以在该对象中创建一个方法以从任何子列表中删除目标:

class BattleSpace(object):
    def __init__(self):
        self.friendly_list = []
        self.enemy_list = []

    def remove(self, target):
        if target in self.friendly_list:
            self.friendly_list.remove(target)
        if target in self.enemy_list:
            self.enemy_list.remove(target)


battle_space = BattleSpace()
battle_space.friendly_list.append(x)
battle_space.remove(x)  # can also do battle_space.friendly_list.remove(x)

编辑:只需阅读 OP 的评论,即希望删除列表中的任何位置。修改后的代码。

【讨论】:

  • 绝对是更好的解决方案。编辑:向Goblin 类添加一个属性来指定它是否友好也是值得的,这样您就可以确切地知道要从哪个列表中删除。
  • 如何在不知道它是否在friendly_list 或enemy_list 中,而只知道它在某处的battle_list 中的情况下从battle_list 中删除x?
  • @Kos 正如 Karin 所说,通过检查两个列表,或者在每个 Goblin 实例上具有一个属性。 self.type = 'friendly''self.type = 'enemy',然后将该变量传递给 Karin 编写的 remove 函数。这是最干净的方式。
  • @Karin 我会删除您最后一行代码中的注释。像您所写的函数中的要点remove() 通常是一种执行任务的方法,而不允许外人直接访问类变量。这就是其他语言中的private 关键字的全部意义所在。应该预料,如果一个函数想要操作 BattleSpace 拥有的列表,它只能通过 BattleSpace 提供的方法来这样做。
  • 小提示:虽然列表理解和过滤器会给你正确的东西,但我宁愿不这样做,因为它们都会创建新列表,而 remove 将从现有列表中删除项目。当然,这样做所节省的内存对于您的用例来说可能可以忽略不计;)
【解决方案2】:

如果知道嵌套列表的索引,可以从父列表索引,调用remove

Battle_Space[0].remove(x)

要从它出现的任何地方删除x,您可以使用列表推导:

Battle_Space = [[j for j in innerlist if j!=x] for innerlist in Battle_Space]

【讨论】:

  • 非常感谢摩西的简洁回答;您在一行中实现了我想要的行为。我将学习更多关于列表理解的知识,这样我就可以在确切知道发生了什么的情况下将其合并到我的代码中。
【解决方案3】:

只需过滤掉那些该死的地精,例如:

import random


class Goblin(object):

    def __init__(self):
        self.Name = "Goblin"
        self.HP = random.randint(15, 20)
        self.Damage = random.randint(5, 10)

x = Goblin()
Friendly_List = list()
Enemy_List = list()
Battle_Space = list([Friendly_List, Enemy_List])
Friendly_List.append(x)
Friendly_List.append(x)
Friendly_List.append(x)
Enemy_List.append(x)

print Battle_Space
for index, army in enumerate(Battle_Space):
    Battle_Space[index] = filter(lambda entity: entity != x, army)
print Battle_Space

代码将从你的星际战斗的所有军队中移除该死的复制地精。

我不是银河战斗的忠实粉丝,地精可以神奇地复制自己吗? :')

编辑

如果您想要一种更 OOP 的方法,您可以将上面的代码转换成类似这样的形式:

import random


class Goblin(object):

    def __init__(self):
        self.Name = "Goblin"
        self.HP = random.randint(15, 20)
        self.Damage = random.randint(5, 10)


class Army(object):

    def __init__(self):
        self.entities = []

    def remove(self, target):
        if target in self.entities:
            self.entities.remove(target)

    def filter(self, target):
        self.entities = filter(
            lambda entity: self.entities != entity, self.entities)


class BattleSpace(object):

    def __init__(self):
        self.armies = []

    def remove(self, target):
        for index, army in enumerate(self.armies):
            army.remove(target)

    def filter(self, target):
        for index, army in enumerate(self.armies):
            army.filter(target)


x = Goblin()
battle_space = BattleSpace()
Friendly_List = Army()
Enemy_List = Army()
battle_space.armies = [Friendly_List, Enemy_List]
Enemy_List.entities.append(x)

print "Initial setup"
print Enemy_List.entities
print Friendly_List.entities

print "After removing"
battle_space.remove(x)
print Enemy_List.entities
print Friendly_List.entities

通过这种方式,您可以轻松地将您的 BattleSpace 扩展到来自不同星球的数以万计的星际军队

【讨论】:

  • 我认为 Karin 建议的 OO 方法是一种更好的方法。到目前为止,更有条理、更通用、更符合 OP 的代码。
  • @jphollowed 好吧,我实际上并不同意你的观点,恕我直言,卡琳的方法将军队与 BattleSpace 课程结合起来,这不是一个好习惯。我已经编辑了我的答案以使其更灵活
  • @Kos 出于好奇,您为什么认为其他答案比这个更好?
  • 他们用更少的代码做我需要做的事,而且我可以理解更多(我还是个初学者),仅此而已
猜你喜欢
  • 2020-04-17
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 1970-01-01
相关资源
最近更新 更多