Ahora sé que no es seguro modificar la lista durante un bucle iterativo. Sin embargo, supongamos que tengo una lista de cadenas y quiero quitar las cadenas. ¿El reemplazo de valores mutables cuenta como modificación?
Ahora sé que no es seguro modificar la lista durante un bucle iterativo. Sin embargo, supongamos que tengo una lista de cadenas y quiero quitar las cadenas. ¿El reemplazo de valores mutables cuenta como modificación?
Respuestas:
Se considera pobre forma. En su lugar, utilice una comprensión de la lista, con asignación de sectores si necesita conservar las referencias existentes a la lista.
a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)
print bse ejecuta la declaración, puede saber si ase modificó en lugar de reemplazarse. Otra posibilidad habría sido print b is aver si ambos todavía se refieren al mismo objeto.
Dado que el siguiente ciclo solo modifica elementos ya vistos, se consideraría aceptable:
a = ['a',' b', 'c ', ' d ']
for i, s in enumerate(a):
a[i] = s.strip()
print(a) # -> ['a', 'b', 'c', 'd']
Que es diferente de:
a[:] = [s.strip() for s in a]
ya que no requiere la creación de una lista temporal y una asignación de la misma para reemplazar el original, aunque sí requiere más operaciones de indexación.
Precaución: aunque puede modificar las entradas de esta manera, no puede cambiar el número de elementos en el listsin arriesgar la posibilidad de encontrar problemas.
Aquí hay un ejemplo de lo que quiero decir: eliminar una entrada desordena la indexación a partir de ese momento:
b = ['a', ' b', 'c ', ' d ']
for i, s in enumerate(b):
if s.strip() != b[i]: # leading or trailing whitespace?
del b[i]
print(b) # -> ['a', 'c '] # WRONG!
(El resultado es incorrecto porque no eliminó todos los elementos que debería tener).
Actualizar
Dado que esta es una respuesta bastante popular, aquí se explica cómo eliminar efectivamente las entradas "en el lugar" (aunque esa no es exactamente la pregunta):
b = ['a',' b', 'c ', ' d ']
b[:] = [entry for entry in b if entry.strip() == entry]
print(b) # -> ['a'] # CORRECT
for i in a? Esto es muy contradictorio, aparentemente diferente de otros idiomas y ha resultado en errores en mi código que tuve que depurar durante un largo período de tiempo. Python Tutorial ni siquiera lo menciona. Aunque debe haber alguna razón para ello?
a[i]y s) para el mismo objeto en la misma línea cuando no es necesario? Prefiero hacer mucho a[i] = a[i].strip().
a[i] = s.strip()solo se realiza una operación de indexación.
enumerate(b)realiza una operación de indexación en cada iteración y está haciendo otra con a[i] =. AFAIK es imposible implementar este bucle en Python con solo 1 operación de indexación por iteración del bucle :(
Una variante más para el bucle, me parece más limpia que una con enumerate ():
for idx in range(len(list)):
list[idx]=... # set a new value
# some other code which doesn't let you use a list comprehension
range(len(list))en Python un olor a código.
enumeratees un generador, no está creando una lista de tuplas, las crea una a la vez a medida que recorre la lista. La única forma de saber cuál es más lenta sería hacerlo timeit.
Está bien modificar cada elemento mientras itera una lista, siempre y cuando no cambie agregar / quitar elementos a la lista.
Puede usar la comprensión de la lista:
l = ['a', ' list', 'of ', ' string ']
l = [item.strip() for item in l]
o simplemente haz el C-stylebucle for:
for index, item in enumerate(l):
l[index] = item.strip()
No, no alterarías el "contenido" de la lista si pudieras mutar las cadenas de esa manera. Pero en Python no son mutables. Cualquier operación de cadena devuelve una nueva cadena.
Si tuviera una lista de objetos que sabía que eran mutables, podría hacerlo siempre y cuando no cambie el contenido real de la lista.
Por lo tanto, tendrá que hacer un mapa de algún tipo. Si utiliza una expresión generadora, [la operación] se realizará a medida que itera y ahorrará memoria.
La respuesta dada por Jemshit Iskenderov e Ignacio Vázquez-Abrams es realmente buena. Se puede ilustrar más con este ejemplo: imagine que
a) Se le da una lista con dos vectores;
b) desea recorrer la lista e invertir el orden de cada una de las matrices
Digamos que tienes
v = np.array([1, 2,3,4])
b = np.array([3,4,6])
for i in [v, b]:
i = i[::-1] # this command does not reverse the string
print([v,b])
Conseguirás
[array([1, 2, 3, 4]), array([3, 4, 6])]
Por otro lado, si lo haces
v = np.array([1, 2,3,4])
b = np.array([3,4,6])
for i in [v, b]:
i[:] = i[::-1] # this command reverses the string
print([v,b])
El resultado es
[array([4, 3, 2, 1]), array([6, 4, 3])]
No queda claro en su pregunta cuáles son los criterios para decidir qué cadenas eliminar, pero si tiene o puede hacer una lista de las cadenas que desea eliminar, puede hacer lo siguiente:
my_strings = ['a','b','c','d','e']
undesirable_strings = ['b','d']
for undesirable_string in undesirable_strings:
for i in range(my_strings.count(undesirable_string)):
my_strings.remove(undesirable_string)
que cambia my_strings a ['a', 'c', 'e']
En resumen, hacer modificaciones en la lista mientras itera la misma lista.
list[:] = ["Modify the list" for each_element in list "Condition Check"]
ejemplo:
list[:] = [list.remove(each_element) for each_element in list if each_element in ["data1", "data2"]]