Как удалить сразу несколько индексов из списка?

Скажем, у меня есть этот список здесь:

list = [a, b, c, d, e, f, g]

Как я могу удалить индексы 2, 3, 4 и 5 в то же время?

pop не принимает несколько значений. Как еще я это сделаю?

Ответ 1

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

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

del my_list[2:6]

который удаляет срез, начинающийся с 2 и заканчивающийся непосредственно перед 6.

Из вашего вопроса неясно, вообще ли вам нужно удалить произвольный набор индексов или если он всегда будет непрерывной последовательностью.

Если у вас есть произвольная коллекция индексов, то:

indexes = [2, 3, 5]
for index in sorted(indexes, reverse=True):
    del my_list[index]

Обратите внимание, что вам нужно удалить их в обратном порядке, чтобы не отбрасывать последующие индексы.

Ответ 2

remove_indices = [1,2,3]
somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]

Пример:

In [9]: remove_indices = [1,2,3]

In [10]: somelist = range(10)

In [11]: somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]

In [12]: somelist
Out[12]: [0, 4, 5, 6, 7, 8, 9]

Ответ 3

Если они смежны, вы можете просто сделать

x[2:6] = []

Если вы хотите удалить несмежные индексы, это немного сложнее.

x = [v for i,v in enumerate(x) if i not in frozenset((2,3,4,5))] 

Ответ 4

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
lst = lst[0:2] + lst[6:]

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

Ответ 5

Если вы можете использовать numpy, вы можете удалить несколько индексов:

>>> import numpy as np
>>> a = np.arange(10)
>>> np.delete(a,(1,3,5))
array([0, 2, 4, 6, 7, 8, 9])

и если вы используете np.r_, вы можете комбинировать срезы с отдельными индексами:

>>> np.delete(a,(np.r_[0:5,7,9]))
array([5, 6, 8])

Однако удаление не является in place, поэтому вам нужно назначить ему.

Ответ 6

Не было большого намека на производительность для разных способов, поэтому я выполнил тест по удалению 5000 элементов из 50000 во всех трех общих подходах, и для меня был победитель numpy (если у вас есть элементы, которые вписываются в numpy)

  • 7.5 сек для понимания перечисляемого списка
  • 0,08 с для удаления элементов в обратном порядке
  • 0.009 sec для numpy.delete

Здесь код, который я запрограммировал (в третьем преобразовании функции из/в список можно удалить, если работа с массивами numpy выполняется нормально):

import time
import numpy as np
import random

def del_list_indexes(l, id_to_del):
    somelist = [i for j, i in enumerate(l) if j not in id_to_del]
    return somelist

def del_list_inplace(l, id_to_del):
    for i in sorted(id_to_del, reverse=True):
        del(l[i])

def del_list_numpy(l, id_to_del):
    arr = np.array(l, dtype='int32')
    return list(np.delete(arr, l))

l = range(50000)
random.shuffle(l)
remove_id = random.sample(range(len(l)), 5000) # 10% ==> 5000

# ...

Ответ 7

Старый вопрос, но у меня есть ответ.

Сначала рассмотрите элементы списка следующим образом:

for x in range(len(yourlist)):
    print '%s: %s' % (x, yourlist[x])

Затем вызовите эту функцию со списком индексов элементов, которые вы хотите поместить. Он достаточно прочный, что порядок списка не имеет значения.

def multipop(yourlist, itemstopop):
    result = []
    itemstopop.sort()
    itemstopop = itemstopop[::-1]
    for x in itemstopop:
        result.append(yourlist.pop(x))
    return result

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

В [73]: mylist = ['a', 'b', 'c', 'd', 'charles']

В [76]: для x в диапазоне (len (mylist)):

      mylist[x])

....

0: a

1: b

2: c

3: d

4: charles

...

В [77]: multipop (mylist, [0, 2, 4])

Out [77]: ['charles', 'c', 'a']

...

В [78]: mylist

Out [78]: ['b', 'd']

Ответ 8

другой вариант (на месте, любая комбинация индексов):

_marker = object()

for i in indices:
    my_list[i] = _marker  # marked for deletion

obj[:] = [v for v in my_list if v is not _marker]