Почему при удалении элемента из списка в цикле for, пропускается след. элемент списка?

Рейтинг: 0Ответов: 3Опубликовано: 26.03.2023

При удалении элемента в цикле for с помощью функции remove или pop почему то пропускается след. элемент списка.
Пример:

cards = [1, 2, 3, 4, 5]
for c in cards:
    if c == 3:
        cards.remove(c)
    print(c)

print(cards)

Результат:

1
2
3
5
[1, 2, 4, 5]

В выводе видно что не печатается 4, интересно почему? а в конечном списке он есть.

Ответы

▲ 1

Потому что удаление элемента сдвигает все последующие элементы списка.

Для наглядности, заменим ваши 12345 на ABCDE.

  • Вот был список ABCDE.
  • Вот у вас идет цикл на 3й итерации вы на элементе C, и вы решили его удалить. Массив стал ABDE.
  • В следующей итерации, вы уже на 4м элементе - смотрим, это элемент E. А D получается "пропущен", действительно.

У вас же еще сложнее - вы храните текущий элемент в переменной c. То что вы его удаляете из списка, не удаляет его из переменной. Получается, что вы элемент из списка удалили, но все равно напечатали, а следующий "пропустили".

▲ 1

Распространённая ошибка среди новичков. Дело в том, что что когда вы итерируетесь с начала списка, и удаляя элементы по очереди все элементы сдвигаются влево, т.к. всегда индексы должны идти по порядку. Для наглядности простой пример:

lst = [i+1 for i in range(10)]  # просто заполняет список
for i in range(len(lst)):
    print(f"index: {i}")
    print(lst)
    if lst[i]%2==0:
        lst.pop(i)

В коде мы бежимся по списку и удаляем каждый чётный элемент в списке, а для удобства так же выводим индекс элемента который будем проверять(я в ручном режиме для простоты понимания добавил стрелочку указывая на какой элемент сейчас "смотрит" программа).

index: 0
 v
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
index: 1
    v
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
index: 2
       v
[1, 3, 4, 5, 6, 7, 8, 9, 10]
index: 3
          v
[1, 3, 5, 6, 7, 8, 9, 10]
index: 4
             v
[1, 3, 5, 7, 8, 9, 10]
index: 5
                v
[1, 3, 5, 7, 9, 10]
index: 6
               v
[1, 3, 5, 7, 9]
IndexError: list index out of range

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

cards = [1, 2, 3, 4, 5]
for c in cards[::-1]: # реверс списка срезами
    if c == 3:
        cards.remove(c)
    print(c)

print(cards)

Вывод программы:

5
4
3
2
1
[1, 2, 4, 5]
▲ 0

Проблему решил с помощью копии списка (очень уж надо было удалить в цикле):

cards = [1, 2, 3, 4, 5]
cards_new = cards.copy()

for c in cards:
   cards = cards_new 
    if c == 3:
        cards_new.remove(c)
    print(c)

1
2
3
4
5
[1, 2, 4, 5]

print(cards)