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

Удалить много элементов списка (python)

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

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

del L[i]

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

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

Doing:

for i in I: 
     del L[i]

Не работает.

Любые идеи?

4b9b3361

Ответ 1

Eine Minuten bitte, Ich hap eine kleine Problemo avec diese Religione. - Эдди Иззард (делает впечатление Мартина Лютера)

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

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]

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

EDITED: изменил "L =..." на "L [:] =..." за ответ Alex Martelli на этот вопрос.

Ответ 2

for i in I:
    del L[i]

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

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

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

Ответ 3

Вы можете использовать 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.

Ответ 4

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

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

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

Ответ 5

L = [ item for item in L if L.index(item) not in I ]