2013-11-13 3 views
2

Im пытается создать набор, основанный на другом наборе, и исключить только один элемент ... (сделать цикл 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) 

точка, мой оператор печати возвращает объект id(x), так что я знаю, что они такие же объект, но они не должны быть , Я отказываюсь от этого набора new_animals.

Любое понимание того, почему это не исключает товар?

+0

Возможно, 'discard' возвращает новый набор, а не модифицирует старый? Наборы могут быть неизменными, но я не могу вспомнить. –

+0

@WaleedKhan: 'set.discard()' работает на месте. 'set()' изменен, 'frozenset()' не является и не имеет метода '.discard()'. –

ответ

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 все время; использование локальных имен достаточно и даже не нужно здесь.

+0

Хорошо заметили! (+1) – NPE

+0

Я думаю, что OP, возможно, пытался это сделать: 'self.new_animals = self.animals.разница ([animal]) ' –

+0

Действительно я тоже пробовал это, вместе с десятком способов, используя списки вместо наборов (О, боже, почему я это сделал.) ... Он по-прежнему не работает так, как должен, но я есть больше материала для исправления и печати, чтобы действительно увидеть, была ли это единственная проблема, которую я имею ... Спасибо за ответ в любом случае. – Matg0d

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')] 

Это хорошо работает в этом случае как код, указанный оказывается симметричным (два животных на том же месте, взаимно уничтожают друг друга). Если бы он был асимметричным (один убивал другого), тогда вам пришлось бы не забудьте проверить оба пути на каждой итерации.

+0

Хорошая идея: 'self.animals_to_die.update ([animal, other_animal])' будет работать хорошо ... –

+0

Я пытался сделать слишком много предположений о типе 'animals_to_die', но давайте поедем с ним. – Duncan

+0

Animals_to_die - это список объектов животных. Вопрос, этот первый код с вещью For и itertools ... Собираюсь проверить каждый элемент в списке против всех остальных? – Matg0d

Смежные вопросы