Pergunta

Qual é a melhor maneira de obter o último item de um iterador em Python 2.6?Por exemplo, digamos

my_iter = iter(range(5))

Qual é o código mais curto/maneira mais limpa de obter 4 de my_iter?

Eu poderia fazer isso, mas não parece muito eficiente:

[x for x in my_iter][-1]
Foi útil?

Solução

item = defaultvalue
for item in my_iter:
    pass

Outras dicas

Use um deque do tamanho 1.

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

Se você estiver usando o Python 3.x:

*_, last = iterator # for a better understanding check PEP 448
print(last)

Se você estiver usando o Python 2.7:

last = next(iterator)
for last in iterator:
    continue
print last


NB:

Geralmente a solução apresentada acima é o que você precisa para casos regulares, mas se você estiver lidando com grande quantidade de dados, é mais eficiente usar um deque do tamanho 1. (fonte)

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

Provavelmente vale a pena usar __reversed__ Se estiver disponível

if hasattr(my_iter,'__reversed__'):
    last = next(reversed(my_iter))
else:
    for last in my_iter:
        pass

Tão simples quanto:

max(enumerate(the_iter))[1]

É improvável que isso seja mais rápido que o vazio por loop devido ao lambda, mas talvez isso dê uma ideia a alguém

reduce(lambda x,y:y,my_iter)

Se o iter estiver vazio, um TypeError será elevado

Lá está isso

list( the_iter )[-1]

Se a duração da iteração for verdadeiramente épica - tanto quanto materializar a lista esgotará a memória - você realmente precisa repensar o design.

eu usaria reversed, exceto que são necessárias apenas sequências em vez de iteradores, o que parece bastante arbitrário.

De qualquer maneira, você terá que correr por todo o iterador. Com a máxima eficiência, se você nunca mais precisar do iterador, poderá simplesmente destruir todos os valores:

for last in my_iter:
    pass
# last is now the last item

Eu acho que esta é uma solução subótima, no entanto.

o Toolz A biblioteca fornece uma boa solução:

from toolz.itertoolz import last
last(values)

Mas adicionar uma dependência não essencial pode não valer a pena por usá-la apenas neste caso.

Veja este código para algo semelhante:

http://excamera.com/sphinx/article-islast.html

Você pode usá -lo para pegar o último item com:

[(last, e) for (last, e) in islast(the_iter) if last]

Eu apenas usaria next(reversed(myiter))

A questão é obter o último elemento de um iterador, mas se o seu iterador for criado aplicando condições a uma sequência, então revertido pode ser usado para encontrar o "primeiro" de uma sequência revertida, apenas olhando para os elementos necessários, aplicando reverter para a própria sequência.

Um exemplo artificial,

>>> seq = list(range(10))
>>> last_even = next(_ for _ in reversed(seq) if _ % 2 == 0)
>>> last_even
8

Alternativamente para iteradores infinitos que você pode usar:

from itertools import islice 
last = list(islice(iterator(), 1000))[-1] # where 1000 is number of samples 

Eu pensei que seria mais lento então deque Mas é tão rápido e na verdade é mais rápido do que o método de loop (de alguma forma)

A pergunta está errada e só pode levar a uma resposta complicada e ineficiente. Para obter um iterador, é claro que você começa a partir de algo que é iterável, que, na maioria dos casos, oferecerá uma maneira mais direta de acessar o último elemento.

Depois de criar um iterador a partir de um iterável, você está preso ao passar pelos elementos, porque essa é a única coisa que um iterável fornece.

Portanto, a maneira mais eficiente e clara não é criar o iterador em primeiro lugar, mas usar os métodos de acesso nativo do iterável.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top