Подтвердить что ты не робот

Ошибка 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). Тогда почему я получаю такую ​​ошибку?

4b9b3361

Ответ 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)