Удалить много элементов списка (python) - PullRequest
15 голосов
/ 20 сентября 2009

У меня есть список Л.

Я могу удалить элемент i, выполнив:

del L[i]

Но что, если у меня есть набор несмежных индексов для удаления?

I=set([i1, i2, i3,...])

Выполнение:

for i in I: 
     del L[i]

Не сработает.

Есть идеи?

Ответы [ 5 ]

31 голосов
/ 20 сентября 2009

Eine Minuten bitte, Ich hap eine Kleine Problemo avec diese Религия. - Эдди Иззард (делает свое впечатление Мартина Лютера)

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

L[:] = [ item for i,item in enumerate(L) if i not in I ]

Кстати, откуда вы взялись за индексы в I? Вы можете объединить логику получения индексов для удаления и построения нового списка. Предполагая, что это список объектов, и вы хотите сохранить только те, которые проходят тест isValid:

L[:] = [ item for item in L if item.isValid() ]

Это гораздо проще, чем:

I = set()
for i in range(len(L)):
    if not L[i].isValid():
        I.add(i)

for i in sorted(I, reverse=True):
    del L[i]

По большей части я превращаю любой вопрос о том, «как удалить из списка ненужные элементы», в «как создать новый список, содержащий только те элементы, которые я хочу».

РЕДАКТИРОВАНИЕ: изменено «L = ...» на «L [:] = ...» согласно ответу Алекса Мартелли на на этот вопрос .

9 голосов
/ 20 сентября 2009
for i in I:
    del L[i]

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

Всегда безопасно удалять элементы из списка в обратном порядке их индексов. Самый простой способ сделать это с помощью sorted ():

for i in sorted(I, reverse=True):
    del L[i]
4 голосов
/ 23 сентября 2015

Вы можете использовать numpy.delete следующим образом:

import numpy as np
a = ['a', 'l', 3.14, 42, 'u']
I = [1, 3, 4]
np.delete(a, I).tolist()
# Returns: ['a', '3.14']

Если вы не против получить в конце массив numpy, вы можете пропустить .tolist(). Вы также должны увидеть некоторые значительные улучшения скорости, что делает это решение более масштабируемым. Я не тестировал его, но numpy операции - это скомпилированный код, написанный на C или Fortran.

1 голос
/ 21 сентября 2009

Если ваши исходные данные списка можно безопасно преобразовать в набор (то есть все уникальные значения и не нужно поддерживать порядок), вы также можете использовать операции набора:

Lset = set(L)
newset = Lset.difference(I)

Вы также можете сделать что-нибудь с Bag / Multiset, хотя это, вероятно, не стоит затраченных усилий. Второе решение listcomp от Paul McGuire, безусловно, лучше для большинства случаев.

0 голосов
/ 25 апреля 2014
L = [ item for item in L if L.index(item) not in I ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...