2012-07-03 26 views

Respuesta

93

Debe hacer esto en un bucle, no hay una operación incorporada para eliminar varios índices a la vez.

Su ejemplo es en realidad una secuencia contigua de índices, por lo que se puede hacer esto:

del my_list[2:6] 

que elimina el corte a partir de las 2 y termina justo antes de las 6.

No está claro a partir su pregunta si, en general, necesita eliminar una colección arbitraria de índices, o si siempre será una secuencia contigua.

Si usted tiene una colección arbitraria de índices, a continuación:

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

Tenga en cuenta que es necesario eliminar en orden inverso de manera que usted no deshacerse de los índices posteriores.

+2

+1 ¿Cómo esta diferente si en vez de 'del my_list [índice]' 'utilizamos my_list.pop (índice)'? ¿Importa? En términos de eficiencia o semántica? – Levon

+0

Disculpe mi comentario, estoy aprendiendo Python, ¿pero Python reindexa la matriz mientras bucle para eliminar? ¿Por qué si haces un bucle en orden normal, genera una excepción de desplazamiento indefinido? – kitensei

+0

@kitensei Hace reindexar, pero como ordena los índices en orden inverso primero, lo estamos eliminando del extremo derecho de la lista, por lo que nunca reindexamos un elemento antes de eliminarlo. –

8

Si son contiguas, que sólo puede hacer

x[2:6] = [] 

Si desea eliminar índices no contiguos, es un poco más difícil.

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

Como nota, la razón por la que tienes que hacerlo con una enumeración es porque no puedes eliminar en algo que estés iterando, eso sería malo. – Trickfire

+0

@Trick Técnicamente, eso solo es cierto si está usando un iterador real. Si usa un int simple para mantener su posición en la lista, no hay problemas, excepto que el índice se omitirá si elimina algo en una posición inferior a la posición actual. – Antimony

+0

Sí, que podría saltear fuera de los límites, generalmente no es algo bueno que hacer. – Trickfire

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

Ejemplo:

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] 
4

Si puede utilizar numpy, a continuación, puede eliminar varios índices:

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

y si se utiliza np.r_ se pueden combinar rebanadas con persona índices:

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

Sin embargo, la eliminación no es in place, por lo que debe asignarla.

0

Pregunta anterior, pero tengo una respuesta.

En primer lugar, examinar los elementos de la lista de este modo:

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

A continuación, llamar a esta función con una lista de los índices de elementos que desea pop. Es lo suficientemente robusto que el orden de la lista no importa.

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

Como extra, el resultado solo debe contener los elementos que desea eliminar.

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

En [76]: para x en el rango (len (mylist)):

 mylist[x]) 

....:

0: a

1: b

2: c

3: d

4: charles

...

En [77]: MultiPOP (mylist, [0, 2, 4])

Fuera [77] : [ 'charles', 'c', 'A']

...

En [78]: mylist

de salida [78]: [ 'b', 'd']

4

no había mucho toque en el rendimiento de las diferentes maneras así que una prueba sobre la eliminación de 5.000 artículos de 50000 en las 3 en general diferentes enfoques, y para mí numpy fue el ganador (si tiene elementos que caben en numpy):

  • 7,5 seg para la comprensión de lista enumerada [4,5 seg en otro PC]
  • 0,08 seg para borrar los elementos de orden inverso [0.017 (!) seg]
  • 0.009 s ec para numpy.delete [0,006 seg]

Aquí está el código I temporizado (en la tercera conversión función desde/a la lista puede ser retirado si se trabaja directamente sobre arrays numpy es ok):

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, id_to_del)) 

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

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

Esta es una operación de un solo paso. No utiliza un bucle y, por lo tanto, se ejecuta rápidamente. Utiliza segmentación de lista.

+0

Debe incluir una explicación para su código. En general, describir cómo y por qué ciertos comandos o códigos resuelven un problema es más útil, ya que ayuda al OP y a otros a resolver problemas similares. –

+0

por favor revise la edición y amablemente instruya. –

+2

preguntándose por qué 1460 días y 23410 visitas, no se les ocurrió esta solución simple. eso es deprimente. –

0

otra opción (en su lugar, cualquier combinación de índices):

_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] 
Cuestiones relacionadas