Fastest way to get the first and last element of a python iterator

10,968

Solution 1

Get the first value with the next() function:

first = last = next(iterable, defaultvalue)
for last in iterable:
    pass

This assumes the iterable is finite.

For an empty iterable, first and last are set to defaultvalue. For an iterable with just one element, first and last will both refer to that one element. For any other finite iterable, first will have the first element, last the very last.

Solution 2

Based on my answer to the linked question:

Probably worth using __reversed__ if it is available. If you are providing the iterator, and there is a sensible way to implement __reversed__ (ie without iterating from end to end) you should do it

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

Solution 3

You can use a deque with a maxlen of 1 to quickly get the last element of a finite iterator:

>>> from collections import deque
>>> last_getter = deque(maxlen=1)
>>> seq = range(10000)
>>> iseq = iter(seq)
>>>
>>> first = last = next(iseq, None)
>>> last_getter.extend(iseq)
>>> if last_getter: last = last_getter[0]
...
>>> print (first, last)
0 9999

Solution 4

According to my tests, islice is up to 3 times faster than for: pass or deque. This would require you to know how many items there will be, though.

last = next(islice(iterable, length - 1, length))

Or if you don't know the full length, but do know that it must be at least n, you could still "skip" to n as a shortcut:

rest = islice(iterable, n, None)
last = next(rest)
for last in rest:
    pass
Share:
10,968
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to perform checks on the first and last elements of an interator. It has several thousand entries, so I need an expeditious method of checking. If found this post, that put me onto this strategy.

    first = True
    for value in iterator:
       if first:
          do_stuff_to_first_iter
          first = False
       else:
          pass
    do_stuff_to_last_iter
    

    Anyone have any opinions on a quicker method of accomplishing this? Thanks a lot!