Самый чистый способ получить последний элемент из итератора Python

StackOverflow https://stackoverflow.com/questions/2138873

Вопрос

Как лучше всего получить последний элемент из итератора в Python 2.6?Например, скажем

my_iter = iter(range(5))

Каков самый короткий/чистый способ получения 4 от my_iter?

Я мог бы сделать это, но это кажется не очень эффективным:

[x for x in my_iter][-1]
Это было полезно?

Решение

item = defaultvalue
for item in my_iter:
    pass

Другие советы

Использовать deque размера 1.

from collections import deque

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

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

Если вы используете Python 3.x:

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

если вы используете Python 2.7:

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


Примечание:

Обычно решение, представленное выше, является тем, что вам нужно для обычных случаев, но если вы имеете дело с большим объемом данных, более эффективно использовать deque размера 1.(источник)

from collections import deque

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

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

Наверное, стоит использовать __reversed__ если оно доступно

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

Так просто как:

max(enumerate(the_iter))[1]

Вряд ли это будет быстрее, чем пустой цикл for из-за лямбды, но, возможно, это даст кому-то еще идею.

reduce(lambda x,y:y,my_iter)

Если итератор пуст, возникает ошибка TypeError.

Вот это

list( the_iter )[-1]

Если длина итерации поистине эпическая — настолько длинная, что материализация списка исчерпает память — тогда вам действительно нужно переосмыслить дизайн.

я хотел бы использовать reversed, за исключением того, что вместо итераторов используются только последовательности, что кажется довольно произвольным.

В любом случае вам придется пройти через весь итератор.При максимальной эффективности, если вам больше не понадобится итератор, вы можете просто удалить все значения:

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

Хотя я думаю, что это неоптимальное решение.

А инструменты библиотека предоставляет хорошее решение:

from toolz.itertoolz import last
last(values)

Но добавление неосновной зависимости может оказаться нецелесообразным, если использовать ее только в этом случае.

Посмотрите этот код для чего-то подобного:

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

вы можете использовать его, чтобы подобрать последний предмет с помощью:

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

я бы просто использовал next(reversed(myiter))

Вопрос в том, чтобы получить последний элемент итератора, но если ваш итератор создается путем применения условий к последовательности, то обратный ход можно использовать для поиска «первого» в обращенной последовательности, просматривая только необходимые элементы, применяя обратная самой последовательности.

Надуманный пример,

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

Альтернативно для бесконечных итераторов вы можете использовать:

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

Я думал, что тогда это будет медленнее deque но это так же быстро и на самом деле быстрее, чем метод цикла (каким-то образом)

Вопрос неправильный и может привести только к сложному и неэффективному ответу.Чтобы получить итератор, вы, конечно, начинаете с чего-то, что является итерируемым, что в большинстве случаев предлагает более прямой способ доступа к последнему элементу.

Как только вы создадите итератор из итерируемого объекта, вы застрянете в прохождении элементов, потому что это единственное, что предоставляет итерируемый объект.

Итак, наиболее эффективный и понятный способ — не создавать итератор вообще, а использовать собственные методы доступа к итерируемому объекту.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top