forma más limpia de acceder al último elemento de Python iterador
-
22-09-2019 - |
Pregunta
¿Cuál es la mejor manera de conseguir el último elemento de un iterador en Python 2.6? Por ejemplo, digamos
my_iter = iter(range(5))
¿Cuál es la más corta de código / forma más limpia de conseguir 4
de my_iter
?
Yo podría hacer esto, pero no parece muy eficiente:
[x for x in my_iter][-1]
Solución
item = defaultvalue
for item in my_iter:
pass
Otros consejos
Usar un deque
de tamaño 1.
from collections import deque
#aa is an interator
aa = iter('apple')
dd = deque(aa, maxlen=1)
last_element = dd.pop()
Si está utilizando 3.x pitón:
*_, last = iterator # for a better understanding check PEP 448
print(last)
si está utilizando Python 2.7:
last = next(iterator)
for last in iterator:
continue
print last
Nota:
Por lo general, la solución presentada anteriormente es el lo que necesita para los casos normales, pero si se trata de gran cantidad de datos, es más eficaz utilizar una deque
de tamaño 1. ( fuente )
from collections import deque
#aa is an interator
aa = iter('apple')
dd = deque(aa, maxlen=1)
last_element = dd.pop()
Probablemente vale la pena utilizar __reversed__
si está disponible
if hasattr(my_iter,'__reversed__'):
last = next(reversed(my_iter))
else:
for last in my_iter:
pass
Tan simple como:
max(enumerate(the_iter))[1]
Esto es poco probable que sea más rápido que el vacío de bucle debido a la lambda, pero tal vez va a dar a alguien una idea
reduce(lambda x,y:y,my_iter)
Si el iter es vacía, se levantó una TypeError
No es esto
list( the_iter )[-1]
Si la longitud de la iteración es verdaderamente épica - tanto tiempo que la materialización de la lista agotará la memoria -. Entonces usted realmente necesidad de replantear el diseño
Yo usaría reversed
, excepto que sólo se necesitan secuencias en lugar de iteradores, lo que parece bastante arbitraria.
De cualquier forma que lo hace, usted tiene que correr a través de todo el iterador. Con la máxima eficacia, si no es necesario el iterador nunca más, sólo podría basura todos los valores:
for last in my_iter:
pass
# last is now the last item
creo que esto es una solución sub-óptima, sin embargo.
El Toolz biblioteca proporciona una buena solución:
from toolz.itertoolz import last
last(values)
Sin embargo, la adición de una dependencia no subyacente podría no valer la pena para usarlo sólo en este caso.
Ver este código para algo similar:
http://excamera.com/sphinx/article-islast.html
se podría utilizar para recoger el último artículo con:
[(last, e) for (last, e) in islast(the_iter) if last]
Yo sólo usaría next(reversed(myiter))
La pregunta es acerca de cómo obtener el último elemento de un iterador, pero si su iterador se crea mediante la aplicación de condiciones a una secuencia, entonces se invierte se puede utilizar para encontrar el "primero" de una secuencia invertida, mirando sólo los elementos necesarios , mediante la aplicación inversa para la propia secuencia.
Un ejemplo artificial,
>>> seq = list(range(10))
>>> last_even = next(_ for _ in reversed(seq) if _ % 2 == 0)
>>> last_even
8
Como alternativa para los iteradores infinitos que puede utilizar:
from itertools import islice
last = list(islice(iterator(), 1000))[-1] # where 1000 is number of samples
pensé que sería más lento que deque
pero es tan rápido y es realmente más rápido que para el método de bucle (de alguna manera)
La pregunta está mal y sólo puede conducir a una respuesta que es complicado e ineficiente. Para obtener un iterador, que, por supuesto, deberá dirigir a algo que es iterable, que serán en la mayoría de los casos ofrecen una forma más directa de acceder al último elemento.
Una vez que se crea un iterador de un iterable que están atrapados en ir a través de los elementos, porque esa es la única cosa que un iterable proporciona.
Por lo tanto, la forma más eficiente y clara no es crear el iterador en el primer lugar, pero para utilizar los métodos de acceso nativos de la iterable.