[Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?
Steven D'Aprano
steve at pearwood.info
Wed Oct 28 19:41:56 EDT 2015
On Wed, Oct 28, 2015 at 02:48:05PM +0000, Flynn, Stephen (L & P - IT) wrote:
> I'm iterating through a list and I'd like to know when I'm at
> the end of the said list, so I can do something different. For example
>
> list_of_things = ['some', 'special', 'things']
> for each_entry in list_of_things:
> print(each_entry)
> if each_entry == list_of_things[-1]: # do something special to
> last entry
> ...etc
>
>
> Is this the idiomatic way to detect you're at the last entry in a list
> as you iterate through it?
But it doesn't detect the last entry. Consider:
list_of_things = ["cheese", "fruit", "cheese", "fish", "cheese"]
Your code will perform the special processing three times.
There's no idiomatic way to do this because it is a fairly unusual thing
to do. Normally we want to process all the items in a list the same way.
But here are some solutions:
(1) Avoid the problem altogether by arranging matters so that the "last
item" isn't in the list at all.
list_of_things = ['some', 'special']
last = 'things'
for each_entry in list_of_things:
print(each_entry)
print(last.upper())
(2) Slicing. Requires a little extra memory, but is probably the closest
to an idiomatic solution for this sort of thing.
list_of_things = ['some', 'special', 'things']
for each_entry in list_of_things[:-1]:
print(each_entry)
print(list_of_things[-1].upper())
(3) Add a sentinel to the list.
list_of_things = ['some', 'special', None, 'things']
for each_entry in list_of_things:
if each_entry is None: break
print(each_entry)
print(list_of_things[-1].upper())
(4) Count the items.
list_of_things = ['some', 'special', 'things']
for i, each_entry in enumerate(list_of_things):
if i == len(list_of_things) - 1: # Watch out for off-by-one errors!
each_entry = each_entry.upper()
print(each_entry)
(5) What if you're dealing with an iterable of unknown length that can't
be sliced? The obvious answer is to convert to a list:
list_of_things = list(things)
but suppose you have some reason for not wanting to do that. (Perhaps
things is truly huge, billions of items.) Something like this should
help:
prev = []
for this in things:
if prev:
print(prev[0])
prev = [this]
print(prev[0].upper())
We can make this a little more efficient if things is an actual
iterator:
things = iter(things)
try:
prev = next(things)
except StopIteration:
# No things at all.
pass
else:
for this in things:
print(prev)
prev = this
print(prev.upper())
--
Steve
More information about the Tutor
mailing list