¿Cómo eliminar elementos de una lista mientras se itera?


Estoy iterando sobre una lista de tuplas en Python, e intento eliminarlas si cumplen con ciertos criterios.

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

¿Qué debo usar en lugar de code_to_remove_tup? No puedo averiguar cómo quitar el artículo de esta manera.

20 answers

Puede usar una comprensión de lista para crear una nueva lista que contenga solo los elementos que no desea eliminar:

somelist = [x for x in somelist if not determine(x)]

O, asignando al slice somelist[:], puede mutar la lista existente para que contenga solo los elementos que desee:

somelist[:] = [x for x in somelist if not determine(x)]

Este enfoque podría ser útil si hay otras referencias a somelist que necesitan reflejar los cambios.

En lugar de una comprensión, también podría usar itertools. En Python 2:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

O en Python 3:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)
 612
Author: David Raznick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-21 22:17:28

Las respuestas que sugieren comprensiones de listas son CASI correctas except excepto que construyen una lista completamente nueva y luego le dan el mismo nombre a la lista antigua que, no modifican la lista antigua en su lugar. Eso es diferente de lo que estaría haciendo mediante la eliminación selectiva, como en la sugerencia de @Lennart it es más rápido , pero si se accede a su lista a través de múltiples referencias, el hecho de que solo esté volviendo a leer una de las referencias y NO altere el objeto de la lista en sí puede conducir a error.

Afortunadamente, es extremadamente fácil obtener tanto la velocidad de la comprensión de la lista COMO la semántica requerida de la alteración en el lugar just solo código:

somelist[:] = [tup for tup in somelist if determine(tup)]

Tenga en cuenta la sutil diferencia con otras respuestas: esta NO es asignar a un barename, sino asignar a un segmento de lista que simplemente resulta ser la lista completa, reemplazando así el contenido de la lista dentro del mismo objeto de lista de Python, en lugar de simplemente volver a crear una referencia (del objeto de lista anterior al nuevo objeto list) como las otras respuestas.

 502
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-28 10:42:00

Primero debe tomar una copia de la lista e iterar sobre ella, o la iteración fallará con lo que pueden ser resultados inesperados.

Por ejemplo (depende del tipo de lista):

for tup in somelist[:]:
    etc....

Un ejemplo:

>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]
 203
Author: Lennart Regebro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-21 22:24:30
for i in xrange(len(somelist) - 1, -1, -1):
    if some_condition(somelist, i):
        del somelist[i]

Tienes que ir hacia atrás de lo contrario es un poco como aserrar la rama del árbol en la que estás sentado: -)

 81
Author: John Machin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-30 15:44:59

Su mejor enfoque para tal ejemplo sería una comprensión de lista

somelist = [tup for tup in somelist if determine(tup)]

En los casos en los que estás haciendo algo más complejo que llamar a una función determine, prefiero construir una nueva lista y simplemente agregarla a medida que avanzo. Por ejemplo

newlist = []
for tup in somelist:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
somelist = newlist

Copiar la lista usando remove podría hacer que su código se vea un poco más limpio, como se describe en una de las respuestas a continuación. Definitivamente no debe hacer esto para listas extremadamente grandes, ya que esto implica primero copiar toda la lista, y también realizar un O(n) remove operación para cada elemento que se elimina, haciendo de esto un algoritmo O(n^2).

for tup in somelist[:]:
    # lots of code here, possibly setting things up for calling determine
    if determine(tup):
        newlist.append(tup)
 45
Author: Eli Courtwright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-30 17:30:54

Para aquellos que les gusta la programación funcional:

somelist[:] = filter(lambda tup: not determine(tup), somelist)

O

from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))
 35
Author: Cide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-24 12:50:20

El tutorial oficial de Python 2 4.2. "para Declaraciones" dice :

Si necesita modificar la secuencia que está iterando mientras está dentro del bucle (por ejemplo, para duplicar elementos seleccionados), se recomienda que primero haga una copia. Iterar sobre una secuencia no hace implícitamente una copia. La notación slice hace esto especialmente conveniente:

>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

Que es lo que se sugirió en: https://stackoverflow.com/a/1207427/895245

La documentación de Python 2 7.3. "The for statement" da el mismo consejo :

Nota: Hay una sutileza cuando la secuencia está siendo modificada por el bucle (esto solo puede ocurrir para secuencias mutables, es decir, listas). Un contador interno se utiliza para realizar un seguimiento de qué elemento se utiliza a continuación, y esto se incrementa en cada iteración. Cuando este contador ha alcanzado la longitud de la secuencia, el bucle termina. Esto significa que si la suite elimina el elemento actual (o anterior) de la secuencia, se omitirá el siguiente elemento (ya que obtiene el índice del elemento actual que ya se ha tratado). Del mismo modo, si la suite inserta un elemento en la secuencia antes del elemento actual, el elemento actual se tratará de nuevo la próxima vez a través del bucle. Esto puede llevar a errores desagradables que se pueden evitar haciendo una copia temporal usando una porción de toda la secuencia, por ejemplo,

for x in a[:]:
    if x < 0: a.remove(x)

Podría Python hacer esto mejor?

Parece que esta API de Python en particular podría mejorarse. Compáralo, por ejemplo, con su homólogo Java ListIterator, que deja claro que no se puede modificar una lista que se itera excepto con el iterador en sí, y le da formas eficientes de hacerlo sin copiar la lista. ¡Vamos, Python!

 32
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-06 14:09:27

Podría ser inteligente crear también una nueva lista si el elemento de la lista actual cumple con los criterios deseados.

Así que:

for item in originalList:
   if (item != badValue):
        newList.append(item)

Y para evitar tener que volver a codificar todo el proyecto con las nuevas listas nombre:

originalList[:] = newList

Nota, de la documentación de Python:

Copiar.copiar (x) Devuelve una copia superficial de x.

Copiar.deepcopy (x) Devuelve una copia profunda de x.

 9
Author: ntk4,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-23 02:33:13

Necesitaba hacer esto con una lista enorme, y duplicar la lista parecía caro, especialmente porque en mi caso el número de eliminaciones sería poco en comparación con los elementos que quedan. Tomé este enfoque de bajo nivel.

array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
    if someTest(array[i]):
        del array[i]
        arraySize -= 1
    else:
        i += 1

Lo que no se es cuan eficiente un par de eliminaciones son comparadas a copiar una lista grande. Por favor, comente si tiene alguna idea.

 8
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-13 20:54:41

Esta respuesta se escribió originalmente en respuesta a una pregunta que desde entonces ha sido marcada como duplicada: Eliminando coordenadas de la lista en python

Hay dos problemas en su código:

1) Cuando se usa remove(), se intenta eliminar enteros mientras que se necesita eliminar una tupla.

2) El bucle for saltará elementos de su lista.

Repasemos lo que sucede cuando ejecutamos tu código:

>>> L1 = [(1,2), (5,6), (-1,-2), (1,-2)]
>>> for (a,b) in L1:
...   if a < 0 or b < 0:
...     L1.remove(a,b)
... 
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: remove() takes exactly one argument (2 given)

El primer problema es que están pasando 'a' y ' b ' a remove(), pero remove() solo acepta un solo argumento. Entonces, ¿cómo podemos hacer que remove () funcione correctamente con tu lista? Tenemos que averiguar qué es cada elemento de su lista. En este caso, cada uno es una tupla. Para ver esto, accedamos a un elemento de la lista (la indexación comienza en 0):

>>> L1[1]
(5, 6)
>>> type(L1[1])
<type 'tuple'>

Aha! Cada elemento de L1 es en realidad una tupla. Así que eso es lo que necesitamos pasar a remove(). Las tuplas en python son muy fáciles, simplemente se hacen encerrando valores entre paréntesis. "a, b" no es una tupla, pero "(a, b)" es una tupla. Así que modificamos su código y lo ejecutamos de nuevo:

# The remove line now includes an extra "()" to make a tuple out of "a,b"
L1.remove((a,b))

Este código se ejecuta sin ningún error, pero veamos la lista que genera:

L1 is now: [(1, 2), (5, 6), (1, -2)]

¿Por qué sigue (1,-2) en su lista? Resulta que modificar la lista mientras se usa un bucle para iterar sobre ella es una muy mala idea sin un cuidado especial. La razón por la que (1, -2) permanece en la lista es que las ubicaciones de cada elemento dentro de la lista cambiaron entre iteraciones de el bucle for. Veamos qué sucede si alimentamos el código anterior con una lista más larga:

L1 = [(1,2),(5,6),(-1,-2),(1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
### Outputs:
L1 is now: [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

Como puede inferir de ese resultado, cada vez que la instrucción condicional se evalúa a true y se elimina un elemento de la lista, la siguiente iteración del bucle omitirá la evaluación del siguiente elemento de la lista porque sus valores ahora se encuentran en diferentes índices.

La solución más intuitiva es copiar la lista, luego iterar sobre la lista original y solo modificar la copia. Puedes probar hacerlo así:

L2 = L1
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
print L2 is L1
del L1
L1 = L2; del L2
print ("L1 is now: ", L1)

Sin embargo, la salida será idéntica a antes:

'L1 is now: ', [(1, 2), (5, 6), (1, -2), (3, 4), (5, 7), (2, 1), (5, -1), (0, 6)]

Esto se debe a que cuando creamos L2, python en realidad no creó un nuevo objeto. En su lugar, simplemente hacía referencia a L2 al mismo objeto que L1. Podemos verificar esto con ' is 'que es diferente de simplemente" equals" (==).

>>> L2=L1
>>> L1 is L2
True

Podemos hacer una copia verdadera usando copy.copia(). Entonces todo funciona como se espera:

import copy
L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
L2 = copy.copy(L1)
for (a,b) in L1:
    if a < 0 or b < 0 :
        L2.remove((a,b))
# Now, remove the original copy of L1 and replace with L2
del L1
L1 = L2; del L2
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

Finalmente, hay una solución más limpia que tener que haga una copia completamente nueva de L1. La función reversed ():

L1 = [(1,2), (5,6),(-1,-2), (1,-2),(3,4),(5,7),(-4,4),(2,1),(-3,-3),(5,-1),(0,6)]
for (a,b) in reversed(L1):
    if a < 0 or b < 0 :
        L1.remove((a,b))
print ("L1 is now: ", L1)
>>> L1 is now: [(1, 2), (5, 6), (3, 4), (5, 7), (2, 1), (0, 6)]

Desafortunadamente, no puedo describir adecuadamente cómo funciona reversed (). Devuelve un objeto 'listreverseiterator' cuando se le pasa una lista. Para propósitos prácticos, se puede pensar en ello como la creación de una copia inversa de su argumento. Esta es la solución que recomiendo.

 7
Author: Cinghiale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:24

Si desea hacer algo más durante la iteración, puede ser bueno obtener tanto el índice (que garantiza que pueda hacer referencia a él, por ejemplo, si tiene una lista de dictados) como el contenido real de los elementos de la lista.

inlist = [{'field1':10, 'field2':20}, {'field1':30, 'field2':15}]    
for idx, i in enumerate(inlist):
    do some stuff with i['field1']
    if somecondition:
        xlist.append(idx)
for i in reversed(xlist): del inlist[i]

enumerate le da acceso al elemento y al índice a la vez. reversed es para que los índices que vas a eliminar más tarde no cambien en ti.

 4
Author: fantabolous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-18 12:30:16

Es posible que desee utilizar filter() disponible como el built-in.

Para más detalles marque aquí

 4
Author: Xolve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-27 07:40:53

Puedes probar con-looping en reversa, así que para some_list harás algo como:

list_len = len(some_list)
for i in range(list_len):
    reverse_i = list_len - 1 - i
    cur = some_list[reverse_i]

    # some logic with cur element

    if some_condition:
        some_list.pop(reverse_i)

De esta manera el índice está alineado y no sufre de las actualizaciones de la lista (independientemente de si pop elemento cur o no).

 3
Author: Queequeg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-10 20:58:49

Una posible solución, útil si desea no solo eliminar algunas cosas, sino también hacer algo con todos los elementos en un solo bucle:

alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
    if x == 'bad':
        alist.pop(i)
        i -= 1
    # do something cool with x or just print x
    print(x)
    i += 1
 3
Author: Alexey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-13 19:38:52

Necesitaba hacer algo similar y en mi caso el problema era la memoria: necesitaba fusionar varios objetos de conjuntos de datos dentro de una lista, después de hacer algunas cosas con ellos, como un nuevo objeto, y necesitaba deshacerse de cada entrada que estaba fusionando para evitar duplicarlos todos y explotar la memoria. En mi caso tener los objetos en un diccionario en lugar de una lista funcionó bien:

```

k = range(5)
v = ['a','b','c','d','e']
d = {key:val for key,val in zip(k, v)}

print d
for i in range(5):
    print d[i]
    d.pop(i)
print d

```

 2
Author: rafa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 11:05:41

TLDR:

Escribí una biblioteca que te permite hacer esto:

from fluidIter import FluidIterable
fSomeList = FluidIterable(someList)  
for tup in fSomeList:
    if determine(tup):
        # remove 'tup' without "breaking" the iteration
        fSomeList.remove(tup)
        # tup has also been removed from 'someList'
        # as well as 'fSomeList'

Es mejor usar otro método si es posible que no requiera modificar su iterable mientras itera sobre él, pero para algunos algoritmos podría no ser tan sencillo. Así que si estás seguro de que realmente quieres el patrón de código descrito en la pregunta original, es posible.

Debería funcionar en todas las secuencias mutables, no solo en las listas.


Completo respuesta:

Editar: El último ejemplo de código en esta respuesta da un caso de uso para por qué a veces es posible que desee modificar una lista en lugar de usar una comprensión de lista. La primera parte de las respuestas sirve como tutorial de cómo una matriz se puede modificar en su lugar.

La solución sigue a esta respuesta (para una pregunta relacionada) de senderle. Que explica cómo el índice de la matriz se actualiza mientras se itera a través de un lista que ha sido modificada. La solución a continuación está diseñada para rastrear correctamente el índice de la matriz incluso si la lista se modifica.

Descarga fluidIter.py desde aquí https://github.com/alanbacon/FluidIterator, es solo un archivo, por lo que no es necesario instalar git. No hay instalador, por lo que deberá asegurarse de que el archivo esté en la ruta de Python. El código ha sido escrito para python 3 y no está probado en python 2.

from fluidIter import FluidIterable
l = [0,1,2,3,4,5,6,7,8]  
fluidL = FluidIterable(l)                       
for i in fluidL:
    print('initial state of list on this iteration: ' + str(fluidL)) 
    print('current iteration value: ' + str(i))
    print('popped value: ' + str(fluidL.pop(2)))
    print(' ')

print('Final List Value: ' + str(l))

Esto producirá la siguiente salida:

initial state of list on this iteration: [0, 1, 2, 3, 4, 5, 6, 7, 8]
current iteration value: 0
popped value: 2

initial state of list on this iteration: [0, 1, 3, 4, 5, 6, 7, 8]
current iteration value: 1
popped value: 3

initial state of list on this iteration: [0, 1, 4, 5, 6, 7, 8]
current iteration value: 4
popped value: 4

initial state of list on this iteration: [0, 1, 5, 6, 7, 8]
current iteration value: 5
popped value: 5

initial state of list on this iteration: [0, 1, 6, 7, 8]
current iteration value: 6
popped value: 6

initial state of list on this iteration: [0, 1, 7, 8]
current iteration value: 7
popped value: 7

initial state of list on this iteration: [0, 1, 8]
current iteration value: 8
popped value: 8

Final List Value: [0, 1]

Arriba tenemos se utilizó el método pop en el objeto fluid list. También se implementan otros métodos iterables comunes, como del fluidL[i], .remove, .insert, .append, .extend. La lista también se puede modificar usando slices (sort y reverse los métodos no están implementados).

La única condición es que solo debe modificar la lista en su lugar, si en cualquier momento fluidL o l se reasignan a un objeto de lista diferente el código no funcionaría. El objeto original fluidL todavía sería utilizado por el bucle for, pero sería queda fuera de nuestro alcance para modificarlo.

Es decir,

fluidL[2] = 'a'   # is OK
fluidL = [0, 1, 'a', 3, 4, 5, 6, 7, 8]  # is not OK

Si queremos acceder al valor de índice actual de la lista no podemos usar enumerar, ya que esto solo cuenta cuántas veces se ha ejecutado el bucle for. En su lugar usaremos el objeto iterador directamente.

fluidArr = FluidIterable([0,1,2,3])
# get iterator first so can query the current index
fluidArrIter = fluidArr.__iter__()
for i, v in enumerate(fluidArrIter):
    print('enum: ', i)
    print('current val: ', v)
    print('current ind: ', fluidArrIter.currentIndex)
    print(fluidArr)
    fluidArr.insert(0,'a')
    print(' ')

print('Final List Value: ' + str(fluidArr))

Esto producirá lo siguiente:

enum:  0
current val:  0
current ind:  0
[0, 1, 2, 3]

enum:  1
current val:  1
current ind:  2
['a', 0, 1, 2, 3]

enum:  2
current val:  2
current ind:  4
['a', 'a', 0, 1, 2, 3]

enum:  3
current val:  3
current ind:  6
['a', 'a', 'a', 0, 1, 2, 3]

Final List Value: ['a', 'a', 'a', 'a', 0, 1, 2, 3]

La clase FluidIterable solo proporciona una envoltura para el objeto list original. El objeto original se puede acceder como una propiedad del objeto fluido como así:

originalList = fluidArr.fixedIterable

Se pueden encontrar más ejemplos / pruebas en la sección if __name__ is "__main__": en la parte inferior de fluidIter.py. Vale la pena mirar estos porque explican lo que sucede en varias situaciones. Tales como: Reemplazar secciones grandes de la lista usando un segmento. O usar (y modificar) el mismo iterable en bucles for anidados.

Como dije para empezar: esta es una solución complicada que dañará la legibilidad de su código y hará que sea más difícil de depurar. Por lo tanto otras soluciones tales como las comprensiones de la lista mencionadas en la respuesta de David Raznick deben ser consideradas primero. Dicho esto, he encontrado ocasiones en las que esta clase me ha sido útil y ha sido más fácil de usar que realizar un seguimiento de los índices de elementos que necesitan eliminarse.


Editar: Como se mencionó en los comentarios, esta respuesta no presenta realmente un problema para el cual este enfoque proporciona una solución. Voy a tratar de abordar esto aquí:

Las comprensiones de la lista proporcionan una forma de generar una nueva lista, pero estos enfoques tienden a mirar cada elemento de forma aislada en lugar del estado actual de la lista en su conjunto.

Es decir,

newList = [i for i in oldList if testFunc(i)]

Pero ¿qué pasa si el resultado de la testFunc depende de los elementos que ya se han añadido a newList? ¿O los elementos que todavía están en oldList que podrían añadirse a continuación? Todavía puede haber una manera de usar una comprensión de lista, pero comenzará a perder su elegancia, y para mí se siente más fácil modificar una lista en lugar.

El siguiente código es un ejemplo de un algoritmo que sufre del problema anterior. El algoritmo reducirá una lista para que ningún elemento sea un múltiplo de cualquier otro elemento.

randInts = [70, 20, 61, 80, 54, 18, 7, 18, 55, 9]
fRandInts = FluidIterable(randInts)
fRandIntsIter = fRandInts.__iter__()
# for each value in the list (outer loop)
# test against every other value in the list (inner loop)
for i in fRandIntsIter:
    print(' ')
    print('outer val: ', i)
    innerIntsIter = fRandInts.__iter__()
    for j in innerIntsIter:
        innerIndex = innerIntsIter.currentIndex
        # skip the element that the outloop is currently on
        # because we don't want to test a value against itself
        if not innerIndex == fRandIntsIter.currentIndex:
            # if the test element, j, is a multiple 
            # of the reference element, i, then remove 'j'
            if j%i == 0:
                print('remove val: ', j)
                # remove element in place, without breaking the
                # iteration of either loop
                del fRandInts[innerIndex]
            # end if multiple, then remove
        # end if not the same value as outer loop
    # end inner loop
# end outerloop

print('')
print('final list: ', randInts)

La salida y la lista reducida final se muestran a continuación

outer val:  70

outer val:  20
remove val:  80

outer val:  61

outer val:  54

outer val:  18
remove val:  54
remove val:  18

outer val:  7
remove val:  70

outer val:  55

outer val:  9
remove val:  18

final list:  [20, 61, 7, 55, 9]
 2
Author: Resonance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:24

Las otras respuestas son correctas, que por lo general es una mala idea eliminar de una lista que estás iterando. La iteración inversa evita las trampas, pero es mucho más difícil seguir el código que hace eso, por lo que generalmente es mejor usar una comprensión de lista o filter.

Hay, sin embargo, un caso en el que es seguro eliminar elementos de una secuencia que está iterando: si solo está eliminando un elemento mientras está iterando. Esto se puede asegurar usando un return o un break. Por ejemplo:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

Esto a menudo es más fácil de entender que una comprensión de lista cuando está haciendo algunas operaciones con efectos secundarios en el primer elemento de una lista que cumple con alguna condición y luego eliminar ese elemento de la lista inmediatamente después.

 1
Author: Beefster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-15 23:42:50

Para cualquier cosa que tenga el potencial de ser realmente grande, utilizo lo siguiente.

import numpy as np

orig_list = np.array([1, 2, 3, 4, 5, 100, 8, 13])

remove_me = [100, 1]

cleaned = np.delete(orig_list, remove_me)
print(cleaned)

Eso debería ser significativamente más rápido que cualquier otra cosa.

 0
Author: CENTURION,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-22 23:36:31

En algunas situaciones, donde está haciendo más que simplemente filtrar una lista de un elemento a la vez, desea que su iteración cambie mientras itera.

Aquí hay un ejemplo donde copiar la lista de antemano es incorrecto, la iteración inversa es imposible y la comprensión de la lista tampoco es una opción.

""" Sieve of Eratosthenes """

def generate_primes(n):
    """ Generates all primes less than n. """
    primes = list(range(2,n))
    idx = 0
    while idx < len(primes):
        p = primes[idx]
        for multiple in range(p+p, n, p):
            try:
                primes.remove(multiple)
            except ValueError:
                pass #EAFP
        idx += 1
        yield p
 0
Author: CodeKid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-21 16:14:52

De inmediato desea crear una copia de la lista para que pueda tenerla como referencia cuando esté iterando y eliminando tuplas en esa lista que cumplan con ciertos criterios.

Entonces depende del tipo de lista que desee para la salida, ya sea una lista de las tuplas eliminadas o una lista de las tuplas que no se eliminan.

Como David señaló, recomiendo la comprensión de lista para mantener los elementos que no desea eliminar.

somelist = [x for x in somelist if not determine(x)]
 -1
Author: spacexengineer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-01 05:42:51