You изменяют длину списка при циклировании по диапазону, который увеличивается до начальной длины списка; удалить один элемент из списка, а последний индекс больше недействителен.
Перемещение, поскольку элементы удаляются из списка по текущему индексу, остальные индексы списка shift; то, что было в индексе i + 1
, теперь находится в индексе i
, и ваш индекс цикла больше не является полезным.
И последнее, но не менее важное: вы зацикливаете до последнего индекса test
, но затем попытайтесь получить доступ к test[i + 1]
; этот индекс не существует, даже если вы не удаляли элементы из списка.
Вы можете использовать while
цикл, чтобы добиться того, что вы хотите сделать:
test = ['aac', 'aad', 'aac', 'asd', 'msc']
i = 0
while i < len(test) - 1:
if test[i][:2] == test[i+1][:2]:
del test[i]
continue
i += 1
Теперь i
проверяется на длине новый каждый цикл итерации, и мы только увеличиваем i
, если ни один элемент не был удален. Обратите внимание, что цикл ограничен длиной минус 1, потому что вы хотите протестировать для test[i + 1]
каждую итерацию.
Обратите внимание, что я использую del test[i]
; нет необходимости сканировать в списке, ища это значение для удаления снова; это может привести к тонким ошибкам, если значения появляются несколько раз в списке, но только позже экземпляры должны быть удалены; например ['aac', 'foo', 'aac', 'aad']
должно привести к ['aac', 'foo', 'aad']
, не['foo', 'aac', 'aad']
, что и test.remove(test[i])
приведет к
Demo:.
>>> test = ['aac', 'aad', 'aac', 'asd', 'msc']
>>> i = 0
>>> while i < len(test) - 1:
... if test[i][:2] == test[i+1][:2]:
... del test[i]
... continue
... i += 1
...
>>> test
['aac', 'asd', 'msc']
Вы можете использовать список понимание, чтобы избежать усадки проблемы списка:
>>> [t for i, t in enumerate(test) if i == len(test) - 1 or t[:2] != test[i + 1][:2]]
['aac', 'asd', 'msc']
Оба подхода требуют только одного цикла через список ввода.
Теперь я понимаю. Сначала я подумал, что len (range (test)) будет обновляться по мере удаления элементов списка. Но потом я понял, что моя мысль была глупой! Я бы использовал метод while, потому что он выглядит лучше всего для меня. Благодарю. Один вопрос: вы использовали метод «продолжить», но это действительно необходимо? –
Если вы не используете 'continue', вам придется использовать' else: '; вы не хотите, чтобы 'i + = 1' запускался, когда вы только что удалили' test [i] '. –
Метод, предложенный @Manoj, должен был работать частично. Этот метод способен обрабатывать ошибку «i + 1 not existing». Но результат совершенно неожиданен. Этот код удаляет только первый элемент списка и выводит ['aad', 'aac'. 'asd', 'msc'] –