modo più pulito per ottenere ultimo elemento da Python iteratore
-
22-09-2019 - |
Domanda
Qual è il modo migliore di ottenere l'ultimo elemento da un iteratore in Python 2.6? Ad esempio, dire
my_iter = iter(range(5))
Qual è il più breve codice / modo più pulito di ottenere 4
da my_iter
?
ho potuto fare questo, ma non sembra molto efficace:
[x for x in my_iter][-1]
Soluzione
item = defaultvalue
for item in my_iter:
pass
Altri suggerimenti
deque
di taglia 1.
from collections import deque
#aa is an interator
aa = iter('apple')
dd = deque(aa, maxlen=1)
last_element = dd.pop()
Se si utilizza python 3.x:
*_, last = iterator # for a better understanding check PEP 448
print(last)
se si utilizza python 2.7:
last = next(iterator)
for last in iterator:
continue
print last
NB:
Di solito la soluzione presentata sopra è la cosa avete bisogno per i casi normali, ma se avete a che fare con grandi quantità di dati, è più efficiente di utilizzare una deque
di dimensioni 1. ( fonte )
from collections import deque
#aa is an interator
aa = iter('apple')
dd = deque(aa, maxlen=1)
last_element = dd.pop()
Probabilmente vale la pena utilizzare __reversed__
se è disponibile
if hasattr(my_iter,'__reversed__'):
last = next(reversed(my_iter))
else:
for last in my_iter:
pass
Per quanto semplice:
max(enumerate(the_iter))[1]
Questa è improbabile che sia più veloce del vuoto per ciclo a causa della lambda, ma forse sarà dare a qualcun altro un'idea
reduce(lambda x,y:y,my_iter)
Se l'iter è vuota, viene sollevata un'eccezione TypeError
C'è questo
list( the_iter )[-1]
Se la lunghezza dell'iterazione è veramente epico - così a lungo che materializzando la lista esaurirà la memoria -., Allora si ha realmente bisogno di ripensare il design
userei reversed
, tranne che richiede solo sequenze invece di iteratori, che sembra piuttosto arbitraria.
In qualsiasi modo lo si fa, si dovrà eseguire attraverso l'intero iteratore. Alla massima efficienza, se non è necessario sempre di nuovo l'iteratore, si può solo buttare tutti i valori:
for last in my_iter:
pass
# last is now the last item
Credo che questa è una soluzione non ottimale, però.
Il Toolz libreria fornisce una bella soluzione:
from toolz.itertoolz import last
last(values)
Ma aggiungere una dipendenza non-core potrebbe non essere la pena per usarlo solo in questo caso.
Vedere questo codice per qualcosa di simile:
http://excamera.com/sphinx/article-islast.html
si potrebbe utilizzarlo per raccogliere l'ultimo elemento con:
[(last, e) for (last, e) in islast(the_iter) if last]
Vorrei solo usare next(reversed(myiter))
La domanda è su come ottenere l'ultimo elemento di un iteratore, ma se il vostro iteratore è creato mediante l'applicazione di condizioni a una sequenza, quindi invertito può essere usato per trovare la "prima" di una sequenza invertita, solo guardando gli elementi necessari , applicando invertire la sequenza stessa.
Un esempio forzato,
>>> seq = list(range(10))
>>> last_even = next(_ for _ in reversed(seq) if _ % 2 == 0)
>>> last_even
8
In alternativa, per infinite iteratori è possibile utilizzare:
from itertools import islice
last = list(islice(iterator(), 1000))[-1] # where 1000 is number of samples
Ho pensato che sarebbe stato più lento di deque
ma è più veloce e in realtà è più veloce quindi per il metodo loop (in qualche modo)
La domanda è sbagliato e può solo portare ad una risposta che è complicato e inefficiente. Per ottenere un iteratore, è ovviamente avvia fuori da qualcosa che è iterabile, che nella maggior parte dei casi, offrire un modo più diretto di accedere l'ultimo elemento.
Una volta creato un iteratore da un iterabile si sono bloccati nel passare attraverso gli elementi, perché questa è l'unica cosa che un iterabile fornisce.
Quindi, il modo più efficace e chiara non è creare l'iteratore, in primo luogo, ma di utilizzare i metodi di accesso nativi del iterabile.