Удалить четные из списка с помощью функции del

Мне не разрешено использовать функцию.remove() для удаления четных чисел в списке, а спецификации говорят: вы будете изменять исходный список, поэтому его id() не должен изменяться. Вот что у меня есть:

def remove_evens(xs):
    for i in range(len(xs)):
        for x in xs:
            if x%2==0:
                del xs[i]
    return xs

Например, если я тестирую функцию и вводю xs=[1,2,3,4,5], возвращается [3,5]. Я не знаю, почему 1 не возвращается

3 ответа

Может быть, что-то вроде этого будет работать для вас.

>>> xs = [1,5,123,6,2,34]
>>> id(xs)
35519496L
>>> lastidx = len(xs) - 1
>>> for i, x in enumerate(reversed(xs)):
...     if x%2==0:
...         del xs[lastidx-i]
...
>>> xs
[1, 5, 123]
>>> id(xs)
35519496L

Это линейное время, потому что оно перебирает список только один раз. Когда вы перебираете список в обратном направлении, вы можете свободно удалять элементы, не изменяя индексы будущих элементов, которые вы еще не зациклили. Кроме того, идентификатор списка не изменяется с этим методом, как вы можете видеть.:)

Вот еще один способ сделать то же самое только с range/xrange а также len,

>>> xs = [1,5,123,6,2,34]
>>> for i in range(len(xs)-1,-1,-1):
...     if xs[i]%2==0:
...         del xs[i]
...
>>> xs
[1, 5, 123]

Оба способа делают одно и то же, поэтому какой бы способ вы ни выбрали, это вопрос предпочтений / личного стиля.

Это потому, что вы перебираете список и изменяете его одновременно. Это означает, что индекс i не всегда правильно, потому что вы только что удалили элемент из списка. Это приводит к пропуску элементов, и поэтому 1 не там

Ты можешь сделать:

def remove_evens(xs):
    return [x for x in xs if x % 2 != 0]

Это использует понимание списка, чтобы создать список без четных чисел. Если вам нужно изменить существующий список, вы можете сделать:

def remove_evens(xs):
    to_remove = []
    for i, x in enumerate(xs):
        if x % 2 == 0:
            to_remove.append(i)
    for j in to_remove:
        del xs[j]
    return xs

Это создает список to_remove который отслеживает положение элементов, которые должны быть удалены.

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

Вот несколько способов, которыми вы можете достичь своей цели:

>>> def deleteEvens(L):
...   dels = []
...   for i,x in enumerate(L):
...     if not x%2:
...       dels.append(i)
...   for d in dels[::-1]:
...     L.pop(d)
... 
>>> L
[1, 2, 3, 4, 5]
>>> deleteEvens(L)
>>> L
[1, 3, 5]

ИЛИ ЖЕ

>>> L = [1,2,3,4,5]
>>> odds = [i for i in L if i%2]
>>> odds
[1, 3, 5]

ИЛИ ЖЕ

>>> def delEvens(L):
...   dels = []
...   for i,x in enumerate(L):
...     if not x%2:
...       dels.append(i)
...   for d in dels[::-1]:
...     del L[d]
... 
>>> L = [1,2,3,4,5]
>>> delEvens(L)
>>> L
[1, 3, 5]
Другие вопросы по тегам