从Python迭代器获取最后一项的最干净方法

问题:从Python迭代器获取最后一项的最干净方法

从Python 2.6的迭代器中获取最后一项的最佳方法是什么?例如说

my_iter = iter(range(5))

什么是获得的最短码/干净的方式4my_iter

我可以做到这一点,但效率似乎并不高:

[x for x in my_iter][-1]

What’s the best way of getting the last item from an iterator in Python 2.6? For example, say

my_iter = iter(range(5))

What is the shortest-code / cleanest way of getting 4 from my_iter?

I could do this, but it doesn’t seem very efficient:

[x for x in my_iter][-1]

回答 0

item = defaultvalue
for item in my_iter:
    pass
item = defaultvalue
for item in my_iter:
    pass

回答 1

使用deque大小为1的。

from collections import deque

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

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

Use a deque of size 1.

from collections import deque

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

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

回答 2

如果您使用的是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()

If you are using Python 3.x:

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

if you are using python 2.7:

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


Side Note:

Usually, the solution presented above is the what you need for regular cases, but if you are dealing with a big amount of data, it’s more efficient to use a deque of size 1. (source)

from collections import deque

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

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

回答 3

__reversed__如果可用,可能值得使用

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

Probably worth using __reversed__ if it is available

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

回答 4

简单如:

max(enumerate(the_iter))[1]

As simple as:

max(enumerate(the_iter))[1]

回答 5

由于存在lambda,这不太可能比空的for循环快,但也许会给别人一个思路

reduce(lambda x,y:y,my_iter)

如果iter为空,则引发TypeError

This is unlikely to be faster than the empty for loop due to the lambda, but maybe it will give someone else an idea

reduce(lambda x,y:y,my_iter)

If the iter is empty, a TypeError is raised


回答 6

有这个

list( the_iter )[-1]

如果迭代的长度确实是史诗般的-如此之长以至于实现列表将耗尽内存-那么您确实需要重新考虑设计。

There’s this

list( the_iter )[-1]

If the length of the iteration is truly epic — so long that materializing the list will exhaust memory — then you really need to rethink the design.


回答 7

我会用 reversed,只是它只序列而不是迭代器,这似乎相当武断。

无论采用哪种方式,都必须遍历整个迭代器。以最高的效率,如果您不再需要迭代器,则可以废弃所有值:

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

我认为这是次佳的解决方案。

I would use reversed, except that it only takes sequences instead of iterators, which seems rather arbitrary.

Any way you do it, you’ll have to run through the entire iterator. At maximum efficiency, if you don’t need the iterator ever again, you could just trash all the values:

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

I think this is a sub-optimal solution, though.


回答 8

图尔茨库提供了一个很好的解决方案:

from toolz.itertoolz import last
last(values)

但是,仅在这种情况下,添加非核心依赖项可能并不值得。

The toolz library provides a nice solution:

from toolz.itertoolz import last
last(values)

But adding a non-core dependency might not be worth it for using it only in this case.


回答 9

参见以下代码以获取类似信息:

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

您可以使用它来拾取最后一个物品:

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

See this code for something similar:

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

you might use it to pick up the last item with:

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

回答 10

我只会用 next(reversed(myiter))

I would just use next(reversed(myiter))


回答 11

问题是关于获取迭代器的最后一个元素,但是如果您的迭代器是通过将条件应用于序列来创建的,则可以通过应用反向来查找反向序列的“第一个”,而只需查看所需的元素即可。与序列本身相反。

一个人为的例子

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

The question is about getting the last element of an iterator, but if your iterator is created by applying conditions to a sequence, then reversed can be used to find the “first” of a reversed sequence, only looking at the needed elements, by applying reverse to the sequence itself.

A contrived example,

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

回答 12

另外,对于无限迭代器,您可以使用:

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

我以为那会慢一点,deque但是它和循环方法一样快,而且实际上快得多(某种程度上)

Alternatively for infinite iterators you can use:

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

I thought it would be slower then deque but it’s as fast and it’s actually faster then for loop method ( somehow )


回答 13

这个问题是错误的,只能导致复杂而低效的答案。要获得迭代器,您当然要从可迭代的事物开始,这在大多数情况下将提供访问最后一个元素的更直接的方法。

从可迭代对象创建迭代器后,您就不得不遍历元素,因为这是可迭代对象唯一提供的内容。

因此,最有效,最清晰的方法不是首先创建迭代器,而是使用迭代器的本机访问方法。

The question is wrong and can only lead to an answer that is complicated and inefficient. To get an iterator, you of course start out from something that is iterable, which will in most cases offer a more direct way of accessing the last element.

Once you create an iterator from an iterable you are stuck in going through the elements, because that is the only thing an iterable provides.

So, the most efficient and clear way is not to create the iterator in the first place but to use the native access methods of the iterable.