2

我试图在另一个集合中创建一个集合,并且只排除一个项目......(在另一个 for 循环中执行一个 for 循环,其中一个对象位于一个集合内,但在第二个循环中不与自身迭代)

代码:

for animal in self.animals:
    self.exclude_animal = set((animal,))
    self.new_animals = set(self.animals)
    self.new_animals.discard(self.exclude_animal) # parameters for a set needs to be a set?

    for other_animal in (self.new_animals):
        if animal.pos[0] == other_animal.pos[0]:
            if animal.pos[1] == other_animal.pos[1]:
                self.animals_to_die.add(animal)
                print other_animal
                print animal
                self.animals_to_die.add(other_animal)

关键是,我的 print 语句返回 object id(x),所以我知道它们是同一个对象,但它们不应该是,我在那个集合上丢弃它new_animals

关于为什么这不排除该项目的任何见解?

4

2 回答 2

7

set.discard()从集合中删除一个项目,但您传入整个集合对象。

您需要删除元素本身,而不是另一个包含元素的集合:

self.new_animals.discard(animal)

演示:

>>> someset = {1, 2, 3}
>>> someset.discard({1})
>>> someset.discard(2)
>>> someset
set([1, 3])

请注意如何2删除,但1仍保留在集合中。

在这里循环设置差异会更容易:

for animal in self.animals:    
    for other_animal in set(self.animals).difference([animal]):
        if animal.pos == other_animal.pos:
            self.animals_to_die.add(animal)
            print other_animal
            print animal
            self.animals_to_die.add(other_animal)

(我假设这.pos是两个值的元组,你可以在这里测试直接相等)。

您不需要一直存储new_animalsself使用本地名称就足够了,这里甚至不需要。

于 2013-11-13T14:55:06.480 回答
1

当您将两只动物都标记为死亡时,您无需将 A 与 B 以及 B 与 A 进行比较(您当前的代码就是这样做的)。您可以使用以下方法确保您只获得独特的动物对itertools.combinations()

for animal, other_animal in itertools.combinations(self.animals, 2):
    if animal.pos==other_animal.pos:
        self.animals_to_die.update([animal, other_animal])

只是为了好玩,我会指出您甚至可以将其作为单个表达式来执行(尽管我认为它作为显式循环读起来更好):

self.animals_to_die.update(sum(((animal,other_animal)
    for animal,other_animal in itertools.combinations(self.animals, 2)
    if animal.pos == other_animal.pos), ()))

为清楚起见,itertools.combinations()为您提供其输入的所有独特组合。第二个参数控制每次选择多少个元素:

>>> list(itertools.combinations(["A", "B", "C", "D"], 2))
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
>>> list(itertools.combinations(["A", "B", "C", "D"], 3))
[('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D')]

这在这种情况下效果很好,因为给出的代码似乎是对称的(同一位置的两只动物相互歼灭)。如果它是不对称的(一个杀死另一个),那么你必须记住在每次迭代中测试两种方式。

于 2013-11-13T15:45:22.193 回答