Самый чистый способ получить последний элемент из итератора Python
-
22-09-2019 - |
Вопрос
Как лучше всего получить последний элемент из итератора в 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
но это так же быстро и на самом деле быстрее, чем метод цикла (каким-то образом)
Вопрос неправильный и может привести только к сложному и неэффективному ответу.Чтобы получить итератор, вы, конечно, начинаете с чего-то, что является итерируемым, что в большинстве случаев предлагает более прямой способ доступа к последнему элементу.
Как только вы создадите итератор из итерируемого объекта, вы застрянете в прохождении элементов, потому что это единственное, что предоставляет итерируемый объект.
Итак, наиболее эффективный и понятный способ — не создавать итератор вообще, а использовать собственные методы доступа к итерируемому объекту.