usuario1487497
Digamos que tengo esta lista aquí:
list = [a, b, c, d, e, f, g]
¿Cómo eliminaría los índices? 2, 3, 4
y 5
¿al mismo tiempo?
pop no acepta múltiples valores. ¿De qué otra manera hago esto?
Debe hacer esto en un ciclo, no hay una operación integrada para eliminar una cantidad de índices a la vez.
Su ejemplo es en realidad una secuencia contigua de índices, por lo que puede hacer esto:
del my_list[2:6]
que elimina el segmento que comienza en 2 y termina justo antes de 6.
No queda claro a partir de su pregunta si, en general, necesita eliminar una colección arbitraria de índices o si siempre será una secuencia contigua.
Si tiene una colección arbitraria de índices, entonces:
indexes = [2, 3, 5]
for index in sorted(indexes, reverse=True):
del my_list[index]
Tenga en cuenta que debe eliminarlos en orden inverso para no descartar los índices posteriores.
-
+1 ¿Cómo sería esto diferente si en lugar de
del my_list[index]
nosotros usamosmy_list.pop(index)
? ¿Importaría? ¿En términos de eficiencia o semántica?– Levón
3 de julio de 2012 a las 3:20
-
Disculpe mi comentario, estoy aprendiendo Python, pero Python reindexa la matriz mientras se repite para eliminar. ¿Por qué si hace un bucle en el orden normal, genera una excepción de compensación indefinida?
– kitensei
20 de junio de 2014 a las 21:19
-
@kitensei Reindexa, pero como primero ordena los índices en orden inverso, lo eliminamos del extremo derecho de la lista, por lo que nunca reindexamos un elemento antes de eliminarlo.
– Andrew Christianson
12/08/2014 a las 21:39
-
Recorriendo los índices hacia atrás. ¡Genio! Estaba aquí soñando con una situación ridícula de índices decrecientes a medida que avanzaba, ¡cuando esto era mucho más elegante!
– Neil
20 abr 2015 a las 22:37
-
@Levon Creo que la principal diferencia es que pop devuelve el valor que eliminas. Dado que no necesitamos los valores que estamos eliminando, probablemente deberíamos usar
del
en este caso, aunque ambos funcionarán.– Pro Q
19 de julio de 2018 a las 2:51
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]
-
Como @C.Yduqoli señala a continuación, esta es la solución más eficiente (no necesitamos seguir reconstruyendo la lista), pero debe convertir
remove_indices
a unset
¡primero!– cz
22 de enero de 2020 a las 9:31
-
Y la solución más elegante.
–David Bridgeland
3 de diciembre de 2021 a las 12:35
Andrés
No hubo muchos indicios sobre el rendimiento de las diferentes formas, así que realicé una prueba para eliminar 5000 elementos de 50000 en los 3 enfoques generalmente diferentes, y para mí, numpy fue el ganador (si tiene elementos que encajan en numpy):
- 7,5 segundos para la comprensión de la lista enumerada [4.5 sec on another PC]
- 0,08 segundos para eliminar elementos en orden inverso [0.017 (!) sec]
- 0.009 segundos para numpy.delete [0.006 sec]
Aquí está el código que cronometré (en la tercera función, la conversión de / a la lista puede eliminarse si está bien trabajar directamente en matrices 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, id_to_del))
l = range(50000)
random.shuffle(l)
remove_id = random.sample(range(len(l)), 5000) # 10% ==> 5000
# ...
-
del_list_indexes
debería ser mucho más rápido si conviertesid_to_del
a un conjunto primero.– C. Yduqoli
2 de diciembre de 2019 a las 7:40
-
@C.Yduqoli Las veces que me sale si usa un
set
porenumerate
son:enumerate
= 0.0041,del
= 0,035,numpy
= 0,0079, que se ha enumerado como el más rápido de lo esperado.– cz
22 de enero de 2020 a las 9:29
si puedes usar entumecidoentonces 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 usas np.r_
puede combinar rebanadas con índices individuales:
>>> np.delete(a,(np.r_[0:5,7,9]))
array([5, 6, 8])
Sin embargo, la eliminación no es in place
así que tienes que asignarle.
Antimonio
Si son contiguos, puedes hacer
x[2:6] = []
Si desea eliminar índices no contiguos, es un poco más complicado.
x = [v for i,v in enumerate(x) if i not in frozenset((2,3,4,5))]
-
Como nota, la razón por la que tiene que hacerlo con una enumeración es porque no puede eliminar algo sobre lo que está iterando, eso sería malo.
– Trickfire
3 de julio de 2012 a las 1:11
-
@Trick Técnicamente, eso solo es cierto si está utilizando un iterador real. Si usa un int simple para mantener su posición en la lista, no hay problemas, excepto que el índice se saltará si elimina algo en una posición inferior a la posición actual.
– Antimonio
3 de julio de 2012 a las 1:15
-
Sí, lo que podría saltar fuera de los límites, generalmente no es algo bueno.
– Trickfire
3 de julio de 2012 a las 1:29
antonio geoghegan
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ápido. Utiliza el corte de lista.
-
Como nota, la razón por la que tiene que hacerlo con una enumeración es porque no puede eliminar algo sobre lo que está iterando, eso sería malo.
– Trickfire
3 de julio de 2012 a las 1:11
-
@Trick Técnicamente, eso solo es cierto si está utilizando un iterador real. Si usa un int simple para mantener su posición en la lista, no hay problemas, excepto que el índice se saltará si elimina algo en una posición inferior a la posición actual.
– Antimonio
3 de julio de 2012 a las 1:15
-
Sí, lo que podría saltar fuera de los límites, generalmente no es algo bueno.
– Trickfire
3 de julio de 2012 a las 1:29
Lars
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]