我试图在另一套中制作一套,只排除一个项目...... (在另一个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语句返回对象id(x)
,所以我知道它们是同一个对象,但它们不应该是,我在该集new_animals
集上丢弃它。
为什么不排除该项目的任何见解?
答案 0 :(得分: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_animals
上存储self
;使用本地名称就足够了,这里甚至不需要。
答案 1 :(得分: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')]
在这种情况下效果很好,因为给出的代码似乎是对称的(同一位置上的两只动物相互湮灭)。如果它是不对称的(一个杀死另一个)那么你必须记住在每次迭代时测试两种方法。