Me gustaría saber la mejor manera (más compacta y "pitónica") de hacer un tratamiento especial para el último elemento en un bucle for. Hay un código que debe llamarse solo entre elementos, que se suprime en el último.
Así es como lo hago actualmente:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
¿Hay alguna forma mejor?
Nota: no quiero hacerlo con hacks como el uso reduce
.;)
Respuestas:
La mayoría de las veces es más fácil (y más barato) hacer que la primera iteración sea el caso especial en lugar del último:
Esto funcionará para cualquier iterable, incluso para aquellos que no tienen
len()
:Aparte de eso, no creo que haya una solución generalmente superior, ya que depende de lo que intente hacer. Por ejemplo, si está creando una cadena a partir de una lista, es naturalmente mejor usar
str.join()
que usar unfor
bucle "con mayúsculas y minúsculas".Usando el mismo principio pero más compacto:
Parece familiar, ¿no? :)
Para @ofko, y otros que realmente necesitan averiguar si el valor actual de un iterable sin
len()
es el último, deberá mirar hacia adelante:Entonces puedes usarlo así:
fuente
if
que podría evitarse si el bucle se dividiera en dos bucles. Sin embargo, esto es relevante solo cuando se itera una gran lista de datos.next()
. Luego exploto que un iterador es iterable por sí mismo, por lo que puedo usarlo en elfor
ciclo hasta el agotamiento, la iteración del segundo al último valor. Durante esto, mantengo el valor actual que recuperé del iterador localmente yyield
el último en su lugar. De esta manera sé que hay un valor más por venir. Después del ciclo for, he informado todos los valores, excepto el último.Aunque esa pregunta es bastante antigua, vine aquí a través de Google y encontré una forma bastante simple: cortar en listas. Digamos que desea poner un '&' entre todas las entradas de la lista.
Esto devuelve '1 y 2 y 3'.
fuente
len(l)=1000000
en este ejemplo, el programa se ejecutará por un tiempo.append
Se recomienda afaik.l=[1,2,3]; l.append(4);
El 'código entre' es un ejemplo del patrón Head-Tail .
Tiene un elemento, seguido de una secuencia de pares (entre elementos). También puede ver esto como una secuencia de (elemento, entre) pares seguidos de un elemento. Generalmente es más simple tomar el primer elemento como especial y todos los demás como el caso "estándar".
Además, para evitar repetir el código, debe proporcionar una función u otro objeto que contenga el código que no desea repetir. Incrustar una declaración if en un bucle que siempre es falso, excepto que una vez es un poco tonto.
Esto es más confiable porque es un poco más fácil de probar, no crea una estructura de datos adicional (es decir, una copia de una lista) y no requiere mucha ejecución desperdiciada de una condición if que siempre es falsa, excepto una vez.
fuente
if
declaraciones, por lo que el argumento de "ejecución desperdiciada" no se cumple.if
s". ¿Obviamente te estás refiriendo a la "limpieza del código"?if
declaración realmente se considera más limpia por la comunidad de Python?Si simplemente está buscando modificar el último elemento
data_list
, simplemente puede usar la notación:Sin embargo, parece que estás haciendo más que eso. No hay nada realmente malo en tu camino. Incluso eché un vistazo rápido a algún código de Django para sus etiquetas de plantilla y hacen básicamente lo que estás haciendo.
fuente
if data != datalist[-1]:
y mantener todo lo demás igual sería la mejor manera de codificar esto en mi opinión.Si los artículos son únicos:
otras opciones:
fuente
Esto es similar al enfoque de Ants Aasma pero sin usar el módulo itertools. También es un iterador rezagado que anticipa un único elemento en la secuencia del iterador:
fuente
Puede usar una ventana deslizante sobre los datos de entrada para echar un vistazo al siguiente valor y usar un centinela para detectar el último valor. Esto funciona en cualquier iterable, por lo que no necesita saber la longitud de antemano. La implementación por pares es de recetas itertools .
fuente
¿No hay posibilidad de iterar sobre todo, excepto el último elemento, y tratar el último fuera del bucle? Después de todo, se crea un bucle para hacer algo similar a todos los elementos sobre los que se bucle; Si un elemento necesita algo especial, no debería estar en el bucle.
(vea también esta pregunta: does-the-last-element-in-a-loop-merece-un-tratamiento-separado )
EDITAR: dado que la pregunta es más sobre el "en el medio", o bien el primer elemento es el especial porque no tiene predecesor, o el último elemento es especial porque no tiene sucesor.
fuente
Me gusta el enfoque de @ ethan-t, pero
while True
desde mi punto de vista es peligroso.Aquí,
data_list
es para que el último elemento sea igual en valor al primero de la lista. Se puede intercambiar con L,data_list
pero en este caso resulta vacío después del bucle.while True
También es posible usarlo si verifica que la lista no está vacía antes del procesamiento o si la verificación no es necesaria (¡ay!).Lo bueno es que es rápido. Lo malo: es destructible (se
data_list
vuelve vacío).La solución más intuitiva:
¡Oh sí, ya lo has propuesto!
fuente
No hay nada malo en su camino, a menos que tenga 100 000 bucles y quiera guardar 100 000 declaraciones "si". En ese caso, puedes ir de esa manera:
Salidas:
Pero realmente, en tu caso siento que es exagerado.
En cualquier caso, probablemente tendrá más suerte con el corte:
o solo :
Eventualmente, una forma de KISS de hacer tus cosas, y eso funcionaría con cualquier iterable, incluidos los que no tienen
__len__
:Ouputs:
Si siento que lo haría de esa manera, me parece simple.
fuente
item
lugar de volver a calcularlo usandolist[-1]
. Pero sin embargo: no creo que esto sea lo que el OP estaba pidiendo, ¿verdad?iterable.__iter__()
- por favor no llame a las__
funciones directamente. Debe seriter(iterable)
.Use el corte y
is
para verificar el último elemento:Advertencia : esto solo funciona si todos los elementos de la lista son realmente diferentes (tienen diferentes ubicaciones en la memoria). Debajo del capó, Python puede detectar elementos iguales y reutilizar los mismos objetos para ellos. Por ejemplo, para cadenas del mismo valor y enteros comunes.
fuente
si está revisando la lista, para mí esto también funcionó:
fuente
Google me trajo a esta vieja pregunta y creo que podría agregar un enfoque diferente a este problema.
La mayoría de las respuestas aquí tratarían con un tratamiento adecuado de un control de bucle for como se le preguntó, pero si data_list es destructible, sugeriría que extraiga los elementos de la lista hasta que termine con una lista vacía:
incluso podría usar while len (element_list) si no necesita hacer nada con el último elemento. Encuentro esta solución más elegante que tratar con next ().
fuente
Para mí, la forma más simple y pitónica de manejar un caso especial al final de una lista es:
Por supuesto, esto también se puede usar para tratar el primer elemento de una manera especial.
fuente
En lugar de contar, también puedes contar:
fuente
Retrasar el manejo especial del último elemento hasta después del ciclo.
fuente
Puede haber múltiples formas. rebanar será más rápido. Agregando uno más que usa el método .index ():
fuente
Asumiendo la entrada como un iterador, esta es una forma de usar tee e izip de itertools:
Manifestación:
fuente
La solución más simple que viene a mi mente es:
Por lo tanto, siempre miramos hacia adelante un elemento retrasando la iteración de procesamiento. Para omitir hacer algo durante la primera iteración, simplemente capto el error.
Por supuesto, debe pensar un poco, para
NameError
que se levante cuando lo desee.También mantenga el `aconsejar
Esto se basa en que el nombre nuevo no se definió previamente. Si eres paranoico, puedes asegurarte de que
new
no exista usando:Alternativamente, también puede usar una declaración if (
if notfirst: print(new) else: notfirst = True
). Pero hasta donde yo sé, la sobrecarga es mayor.así que espero que los gastos generales sean ilegibles.
fuente
Cuente los artículos una vez y manténgase al día con la cantidad de artículos restantes:
De esta manera solo evalúa la longitud de la lista una vez. Muchas de las soluciones en esta página parecen suponer que la longitud no está disponible por adelantado, pero eso no es parte de su pregunta. Si tienes la longitud, úsala.
fuente
Una solución simple que viene a la mente sería:
Se puede lograr una segunda solución igualmente simple utilizando un contador:
fuente