Ошибка python: индекс индекса вне диапазона
Я написал простую программу python
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
Это дает мне ошибку "индекс индекса вне диапазона" в строке if l[i]==0:
После отладки я мог понять, что i
получает прирост, а список уменьшается.
Однако у меня есть условие завершения цикла i < len(l)
. Тогда почему я получаю такую ошибку?
Ответы
Ответ 1
Вы сокращаете длину своего списка l
по мере его перебора по мере того, как вы приближаетесь к концу ваших индексов в операторе диапазона, некоторые из этих индексов больше не действительны.
Похоже, что вы хотите сделать:
l = [x for x in l if x != 0]
который вернет копию l
без каких-либо элементов, которые были бы нулевыми (эта операция называется ). путь). Вы могли бы даже сократить эту последнюю часть до if x
, поскольку ненулевые числа оцениваются до True
.
Нет такой вещи, как условие завершения цикла i < len(l)
, в том, как вы написали код, потому что len(l)
предварительно вычисляется перед циклом, а не переоценивается на каждой итерации. Вы могли бы написать его таким образом, однако:
i = 0
while i < len(l):
if l[i] == 0:
l.pop(i)
else:
i += 1
Ответ 2
Выражение len(l)
оценивается только один раз, в момент вычисления значения range()
. Объект диапазона, построенный в это время, не изменяется; он ничего не может знать об объекте l
.
P.S. l
- это паршивое имя для значения! Он выглядит как цифра 1 или заглавная буква I.
Ответ 3
Вы изменяете размер списка во время итерации по нему, что, вероятно, не то, что вы хотите, и является причиной вашей ошибки.
Изменить: Как другие ответили и прокомментировали, перечислить понимание лучше, чем первый выбор, и особенно в ответ на этот вопрос. Я предложил это как альтернативу по этой причине, и, хотя это не лучший ответ, он по-прежнему решает проблему.
Итак, в этом примечании вы также можете использовать filter
, который позволяет вам вызывать функцию для оценки элементов в списке, который вам не нужен.
Пример:
>>> l = [1,2,3,0,0,1]
>>> filter(lambda x: x > 0, l)
[1, 2, 3]
Живи и учись. Простое, лучше, если вам нужно, чтобы вещи были сложными.
Ответ 4
Что Марк Рушаков сказал, что это правда, но если вы итерации в противоположном направлении, можно также удалить элементы из списка в for-loop. Например.
x = [1,2,3,0,0,1]
for i in range(len(x)-1, -1, -1):
if x[i] == 0:
x.pop(i)
Это похоже на высокое здание, которое падает сверху вниз: даже если оно находится в середине краха, вы все равно можете "enter" в него и посещать все еще не разрушенные полы.
Ответ 5
Я использую python 3.3.5. Вышеупомянутое решение использования цикла while не работает для меня. Даже если я положил print (i)
после len(l)
, это дало мне ошибку. Я запускал тот же код в командной строке (shell) [окно, которое появляется при запуске функции], оно выполняется без ошибок. То, что я сделал, было рассчитано len (l) вне функции в основной программе и передало длину в качестве параметра. Это сработало. Иногда Python странный.
Ответ 6
Проблема заключалась в том, что вы попытались изменить список, который вы указали в цикле, который использовал список len()
. Когда вы удаляете элемент из списка, новый len()
вычисляется в следующем цикле.
Например, после первого запуска, когда вы удалили (i)
с помощью l.pop(i)
, это произошло успешно, но в следующем цикле длина списка изменилась, поэтому все номера индексов были сдвинуты. В какой-то момент цикл пытается запустить более короткий список, забрасывая ошибку.
Выполнение этого вне цикла работает, однако лучше было бы создать и новый список, сначала объявив и пустым списком до цикла, а затем в цикле добавьте все, что вы хотите сохранить в новом списке.
Для тех из вас, кто, возможно, пришел к одной и той же проблеме.
Ответ 7
Понимание списка приведет вас к решению.
Но правильный способ копирования объекта в python заключается в использовании копии модуля python - операции мелкой и глубокой копии.
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
Если вместо этого
import copy
l=[1,2,3,0,0,1]
duplicate_l = copy.copy(l)
for i in range(0,len(l)):
if l[i]==0:
m.remove(i)
l = m
Тогда ваш собственный код сработал бы.
Но для оптимизации понимание списка является хорошим решением.
Ответ 8
Я думаю, что лучший способ решить эту проблему:
l = [1, 2, 3, 0, 0, 1]
while 0 in l:
l.remove(0)
Вместо перебора списка я удаляю 0
, пока в списке нет 0
Ответ 9
Я думаю, что большинство решений здесь говорят о понимании списка, но если вы хотите выполнить удаление на месте и сохранить сложность пространства на уровне O (1); Решение:
i = 0
for j in range(len(arr)):
if (arr[j] != 0):
arr[i] = arr[j]
i +=1
arr = arr[:i]
Ответ 10
x=[]
x = [int(i) for i in input().split()]
i = 0
while i < len(x):
print(x[i])
if(x[i]%5)==0:
del x[i]
else:
i += 1
print(*x)