Уведомления

Группа в Telegram: @pythonsu

#1 Март 4, 2020 09:30:58

pavel13079
Зарегистрирован: 2020-02-26
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

функции

Напишите функцию modify_list(l), которая принимает на вход список целых чисел, удаляет из него все нечётные значения, а чётные нацело делит на два. Функция не должна ничего возвращать, требуется только изменение переданного списка, например:

lst =
print(modify_list(lst)) # None
print(lst) #
modify_list(lst)
print(lst) #

lst =
modify_list(lst)
print(lst) #

мой код

 lst = [1, 2, 3, 4, 5, 6]
def modify_list(l):
    i=0
    le=len(l)-1
    while i<le:
        if l[i]%2==0:
            l[i]=l[i]//2
            i+=1
        else:
            del l[i] 
print(modify_list(lst))  # None
print(lst)               # [1, 2, 3]
modify_list(lst)
print(lst) 

Подскажите почему ошибка?

if l%2==0:
IndexError: list index out of range

Офлайн

#2 Март 4, 2020 10:50:55

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

функции

pavel13079
1) Вы зафиксировали длину списка

 le=len(l)-1
2) Ваш цикл будет выполняться как минимум le раз
3) Вы уменьшаете длину списка в цикле
 del l[i] 

Это значит, что в какой-то момент условие i<le будет соблюдаться (le - длина исходного списка), но в списке будет меньше элементов, чем i.

Ваш алгоритм страдает одним недостатком - вы итерируетесь по списку и одновременно изменяете его длину.
Как вы думаете происходит перебор списка? На самом деле никакой магии нет - это все тот же цикл со счетчиком. Чтобы получить следующий элемент, надо знать текщий индекс, увеличить его на единицу и обратиться к массиву по индексу.
Вот наш исходный список и его индексы
    
[1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5]
мы перебираем список, счетчик указывает на элемент с индексом 2
    
[1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5]
       ^
counter = 2
l[counter] = 3
теперь вы удалили этот элемент
   
del l[2]
[1, 2, 4, 5, 6]
[0, 1, 2, 3, 4]
        ^
counter = 2

теперь происходит следующая итерация цикла - счетчик увеличивается
   
counter += 1
[1, 2, 4, 5, 6]
[0, 1, 2, 3, 4]
           ^       
counter = 3
l[counter] = 5

таким образом значение списка 4 никогда не попадет в цикл - вы его пропустили



Отредактировано FishHook (Март 4, 2020 10:51:48)

Офлайн

#3 Март 4, 2020 11:28:09

Rafik
Зарегистрирован: 2018-09-04
Сообщения: 231
Репутация: +  27  -
Профиль   Отправить e-mail  

функции

Надо, после удаления элемента из списка, убавить le. Тогда твоя функция отработает нормально.

Отредактировано Rafik (Март 4, 2020 11:28:34)

Офлайн

#4 Март 4, 2020 15:19:53

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

функции

Rafik
Тогда твоя функция отработает нормально.
нет не отработает, я для кого писал выше

 l = [0, 1, 2, 3, 4]
le = len(l) - 1
i = 0
while i < le:
    print (i, l[i])
    le -= 1
    i += 1
    del l[i]

C:\Python27\python.exe D:/tests/test.py
(0, 0)
(1, 2)
Вопрос: где 1, 3 и 4?



Офлайн

#5 Март 5, 2020 06:16:26

Rafik
Зарегистрирован: 2018-09-04
Сообщения: 231
Репутация: +  27  -
Профиль   Отправить e-mail  

функции

FishHook
нет не отработает …
Скорее всего, ошибаетесь.
В коде у ТС, в ветке с del, счётчик i не наращивается. Индекс, у него, наращивается только в ветке с не удаляемым элементом.
Следующий элемент списка, после удаления, будет под тем же индексом, под каким был удалённый элемент. Значение индекса i осталось тем же самым для следующей “итерации”. В итоге, всё должно отработать нормально.

Отредактировано Rafik (Март 5, 2020 06:43:54)

Офлайн

#6 Март 5, 2020 10:51:48

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

функции

Rafik

Скорее всего, ошибаетесь.
Вполне может быть. Я бы сделал вот так, это более питонячий код, как мне кажется


 def modify_list(l):
    ln = len(l) - 1
    for i, item in enumerate(reversed(l)):
        index = ln - i
        if item % 2 == 0:
            l[index] = item // 2
            continue
        del l[index]



Офлайн

#7 Март 5, 2020 14:19:10

Rafik
Зарегистрирован: 2018-09-04
Сообщения: 231
Репутация: +  27  -
Профиль   Отправить e-mail  

функции

FishHook, зачем реверсить список? Врубился. Наверное, это один из самых оптимальных вариантов.

UPD. Вот такой вариант тоже работает:

 lst = [0,1,2,3,4,5,6,7]
ln = len(lst) - 1
for i in range(ln, -1, -1):
    if lst[i] % 2 == 0:
        lst[i] = lst[i] // 2
    else:
        del lst[i]
print(lst)
Здесь идём от конца списка. Удаляемый элемент списка всегда находится в уже отработанной части списка.

Отредактировано Rafik (Март 5, 2020 17:49:28)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version