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

Как удалить элемент из списка python, если условие True?

Возможный дубликат:
Удалить элементы из списка, итерации в Python

Я пытаюсь удалить элемент из списка в python:

x = ["ok", "jj", "uy", "poooo", "fren"]
for item in x:
    if len(item) != 2:
        print "length of %s is: %s" %(item, len(item))
        x.remove(item)

Но он не удаляет элемент "fren". Любые идеи?

4b9b3361

Ответ 1

Вы не можете удалять элементы из списка, итерации по нему. Гораздо проще построить новый список на основе старого:

y = [s for s in x if len(s) == 2]

Ответ 2

hymloth и sven отвечают на работу, но они не изменяют список (создайте новый). Если вам нужна модификация объекта, вам нужно назначить срез:

x[:] = [value for value in x if len(value)==2]

Однако для больших списков, в которых вам нужно удалить несколько элементов, это потребляемая память, но она работает в O (n).

glglgl answer страдает сложностью O (n²), потому что list.remove - O (n).

В зависимости от структуры ваших данных вы можете предпочесть отметить индексы элементов для удаления и использовать del для удаления по индексу:

to_remove = [i for i, val in enumerate(x) if len(val)==2]
for index in reversed(to_remove): # start at the end to avoid recomputing offsets
    del x[index]

Теперь del x[i] также O (n), потому что вам нужно скопировать все элементы после индекса i (список - это вектор), поэтому вам нужно будет протестировать это против ваших данных. Тем не менее это должно быть быстрее, чем использование remove, потому что вы не оплачиваете стоимость этапа поиска для удаления, а стоимость копирования в обоих случаях одинакова.

[править] Очень хорошая версия на месте, O (n) с ограниченными требованиями к памяти, любезно предоставлена ​​@Sven Marnach. Он использует itertools.compress, который был введен в python 2.7:

from itertools import compress

selectors = (len(s) == 2 for s in x)
for i, s in enumerate(compress(x, selectors)): # enumerate elements of length 2
    x[i] = s # move found element to beginning of the list, without resizing
del x[i+1:]  # trim the end of the list

Ответ 3

x = [i for i in x if len(i)==2]

Ответ 4

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

Обходной путь может быть:

x = ["ok", "jj", "uy", "poooo", "fren"]
for item in x[:]: # make a copy of x
    if len(item) != 2:
        print "length of %s is: %s" %(item, len(item))
        x.remove(item)

Ответ 5

Уже упомянутый подход к пониманию списка, вероятно, лучший выбор. Но если вы абсолютно хотите сделать это на месте (например, если x действительно велико), здесь один из способов:

x = ["ok", "jj", "uy", "poooo", "fren"]
index=0
while index < len(x):
    if len(x[index]) != 2:
        print "length of %s is: %s" %(x[index], len(x[index]))
        del x[index]
        continue
    index+=1