Этот ответ был первоначально написан в ответ на вопрос, который был помечен как дубликат:
Удаление координат из списка на python
В вашем коде есть две проблемы:
1) При использовании remove () вы пытаетесь удалить целые числа, тогда как вам нужно удалить кортеж.
2) Цикл for пропустит элементы в вашем списке.
Давайте рассмотрим, что произойдет, когда мы выполним ваш код:
>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
... if a < 0 or b < 0:
... L1.remove(a,b)
...
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)
Первая проблема заключается в том, что вы передаете оба «a» и «b» в remove (), но remove () принимает только один аргумент. Итак, как мы можем заставить remove () правильно работать с вашим списком? Нам нужно выяснить, что представляет собой каждый элемент вашего списка. В этом случае каждый из них является кортежем. Чтобы увидеть это, давайте перейдем к одному элементу списка (индексация начинается с 0):
>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>
Aha! Каждый элемент L1 на самом деле является кортежем. Так вот что мы должны передать, чтобы удалить (). Кортежи в python очень просты, они просто создаются путем заключения значений в скобки. «a, b» не является кортежем, но «(a, b)» является кортежем. Поэтому мы модифицируем ваш код и запускаем его снова:
# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))
Этот код выполняется без ошибок, но давайте посмотрим на список, который он выводит:
L1 is now: [(1, 2), (5, 6), (1, -2)]
Почему (1, -2) все еще в вашем списке? Оказывается, изменение списка при использовании цикла для его перебора - очень плохая идея без особой тщательности. Причина того, что (1, -2) остается в списке, заключается в том, что местоположения каждого элемента в списке менялись между итерациями цикла for. Давайте посмотрим, что произойдет, если мы добавим приведенный выше код в более длинный список:
L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Как вы можете сделать из этого результата, каждый раз, когда условный оператор оценивается как true и элемент списка удаляется, следующая итерация цикла будет пропускать оценку следующего элемента в списке, поскольку его значения теперь расположены в разные индексы.
Наиболее интуитивным решением является копирование списка, затем итерация по исходному списку и изменение только копии. Вы можете попробовать сделать это так:
L2 = L1
for (a,b) in L1:
if a < 0 or b < 0 :
L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)
Однако вывод будет идентичен предыдущему:
'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]
Это потому, что когда мы создавали L2, python фактически не создавал новый объект. Вместо этого он просто ссылался на L2 на тот же объект, что и L1. Мы можем проверить это с помощью «is», которое отличается от просто «равно» (==).
>>> L2=L1
>>> L1 is L2
True
Мы можем сделать истинную копию, используя copy.copy (). Тогда все работает как положено:
import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
if a < 0 or b < 0 :
L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]
Наконец, есть одно более чистое решение, чем создание совершенно новой копии L1. Функция реверсирования ():
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
if a < 0 or b < 0 :
L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]
К сожалению, я не могу адекватно описать, как работает reversed (). Он возвращает объект 'listreverseiterator', когда ему передается список. В практических целях вы можете думать об этом как о создании обращенной копии аргумента. Это решение, которое я рекомендую.