У меня есть список L.
Я могу удалить элемент i, выполнив:
del L[i]
Но что, если у меня есть набор непересекающихся индексов для удаления?
I=set([i1, i2, i3,...])
Doing:
for i in I:
del L[i]
Не работает.
Любые идеи?
У меня есть список L.
Я могу удалить элемент i, выполнив:
del L[i]
Но что, если у меня есть набор непересекающихся индексов для удаления?
I=set([i1, i2, i3,...])
Doing:
for i in I:
del L[i]
Не работает.
Любые идеи?
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 на этот вопрос.
for i in I:
del L[i]
не будет работать, потому что (в зависимости от заказа) вы можете аннулировать итератор - это обычно отображается как некоторые элементы, которые вы хотели удалить, оставаясь в списке.
Всегда безопасно удалять элементы из списка в обратном порядке их индексов. Самый простой способ сделать это - отсортировать():
for i in sorted(I, reverse=True):
del L[i]
Вы можете использовать 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.
Если исходные данные списка можно безопасно превратить в набор (т.е. все уникальные значения и не нужно поддерживать порядок), вы также можете использовать операции набора:
Lset = set(L)
newset = Lset.difference(I)
Возможно, вы также можете что-то сделать с помощью Bag/Multiset, хотя, вероятно, это не стоит усилий. Paul McGuire второе решение listcomp, безусловно, подходит для большинства случаев.
L = [ item for item in L if L.index(item) not in I ]