Quel est le meilleur moyen d'obtenir le dernier élément d'un itérateur dans Python 2.6? Par exemple, disons
my_iter = iter(range(5))
Quel est le moyen le plus court/le plus propre d’obtenir 4
de my_iter
?
Je pourrais le faire, mais cela ne semble pas très efficace:
[x for x in my_iter][-1]
item = defaultvalue
for item in my_iter:
pass
Utilisez une deque
de taille 1.
from collections import deque
#aa is an interator
aa = iter('Apple')
dd = deque(aa, maxlen=1)
last_element = dd.pop()
Si vous utilisez python 3.x:
*_, last = iterator # for a better understanding check PEP 448
print(last)
si vous utilisez Python 2.7:
last = next(iterator)
for last in iterator:
continue
print last
NB:
La solution présentée ci-dessus correspond généralement à ce dont vous avez besoin pour les cas normaux, mais si vous traitez avec une grande quantité de données, il est plus efficace d'utiliser une variable deque
de taille 1. ( source )
from collections import deque
#aa is an interator
aa = iter('Apple')
dd = deque(aa, maxlen=1)
last_element = dd.pop()
Probablement utile d'utiliser __reversed__
s'il est disponible
if hasattr(my_iter,'__reversed__'):
last = next(reversed(my_iter))
else:
for last in my_iter:
pass
Aussi simple que:
max(enumerate(the_iter))[1]
Il est peu probable que cela soit plus rapide que la boucle vide pour cause à cause du lambda, mais peut-être que cela donnera à quelqu'un d'autre une idée
reduce(lambda x,y:y,my_iter)
Si l'itérateur est vide, une erreur TypeError est déclenchée
Il y a ceci
list( the_iter )[-1]
Si la longueur de l'itération est vraiment épique - si longue que la matérialisation de la liste épuisera la mémoire - alors vous devez vraiment repenser le design.
J'utiliserais reversed
, sauf qu'il ne prend que des séquences au lieu d'itérateurs, ce qui semble plutôt arbitraire.
Quoi que vous fassiez, vous devrez parcourir l'itérateur en entier. Avec une efficacité maximale, si vous n'avez plus jamais besoin de l'itérateur, vous pouvez simplement supprimer toutes les valeurs:
for last in my_iter:
pass
# last is now the last item
Je pense cependant qu’il s’agit d’une solution sous-optimale.
Voir ce code pour quelque chose de similaire:
http://excamera.com/sphinx/article-islast.html
vous pouvez l'utiliser pour récupérer le dernier élément avec:
[(last, e) for (last, e) in islast(the_iter) if last]
Je voudrais juste utiliser next(reversed(myiter))
Alternativement pour des itérateurs infinis, vous pouvez utiliser:
from itertools import islice
last = list(islice(iterator(), 1000))[-1] # where 1000 is number of samples
Je pensais que ce serait plus lent que deque
mais c'est aussi rapide et en fait plus rapide que la méthode de boucle (en quelque sorte)
La bibliothèque toolz fournit une solution intéressante:
from toolz.itertoolz import last
last(values)
Cependant, l'ajout d'une dépendance non essentielle ne vaut peut-être pas la peine de l'utiliser uniquement dans ce cas.
La question concerne l’obtention du dernier élément d’un itérateur, mais si votre itérateur est créé en appliquant des conditions à une séquence, alors inversé peut être utilisé pour trouver le "premier" d’une séquence inversée, en regardant uniquement les éléments nécessaires, en appliquant inverser la séquence elle-même.
Un exemple artificiel,
>>> seq = list(range(10))
>>> last_even = next(_ for _ in reversed(seq) if _ % 2 == 0)
>>> last_even
8