web-dev-qa-db-fra.com

Le moyen le plus propre d'obtenir le dernier élément de l'itérateur Python

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]
86
Peter
item = defaultvalue
for item in my_iter:
    pass
77
Thomas Wouters

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()
48
martin23487234

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()
34
DhiaTN

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
30
John La Rooy

Aussi simple que:

max(enumerate(the_iter))[1]
19
Chema Cortes

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

19
John La Rooy

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.

8
S.Lott

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.

4
Chris Lutz

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]
1
James Bowman

Je voudrais juste utiliser next(reversed(myiter))

0
thomas.mac

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)

0
qocu

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.

0
lumbric

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
0
Wyrmwood