Home > Back-end >  Why does this reversed for loop miss the last item?
Why does this reversed for loop miss the last item?

Time:09-21

I want to reverse loop through a table and join the table items to make a string. This code works fine but it misses the last item of the table :

 t = [0, 0, 2, 6, 14, 4, 7, 0]
 for i in range(len(t) - 1, 0, -1):
     res = str(t[i])   res
 return res

It prints 02614470 instead of 002614470.

I know if I change 0 to -1 in the loop parameter it would work properly but I want to understand why. It seems that when I want to use -1 as step, the middle parameter (0 in this case ) adds 1. So for example if I want the loop to stop at index 1 I have to write 0 in the parameter. Is that right?

That's my thought process but I don't know if it's correct.

CodePudding user response:

The typical construction of a for loop with range() is:

t=[0,0,2,6,14,4,7,0]
for i in range(0,len(t)):
    print(f"{i}, {t[i]}")

This makes sense to iterate through a list of items which starts at zero and is len() long. Since we start at zero, we have to stop at one less than the value returned for len(t), so range() is built to accommodate this most common case. As you noted in your case, since you are reversing this you would have to iterate through and use a -1 to capture the zero'th index in the list. Fortunately, you can use the following syntax to reverse the range, which leads to better readability:

t=[0,0,2,6,14,4,7,0]
for i in reversed(range(0,len(t))):
    print(f"{i}, {t[i]}")

CodePudding user response:

The second parameter in the range is a stop value so it is excluded from the generation.

for example, when you do range(10), Python processes this as range(0,10) and yields values 0,1,2,...,7,8,9 (i.e. not 10)

Going in reverse, if you want zero to be included, you have to set the stop value at the next lower value past zero (i.e. -1)

CodePudding user response:

Other answers have explained that range does not include the end number. It always stops one short of the end, whether the range is forward or backward.

I'd like to add some more "Pythonic" ways to write the loop. As a rule of thumb try to avoid looping over list indices and instead loop over the items directly.

things = [...]

# Forward over items
for thing in things:
    print(thing)

# Backward over items
for thing in reversed(things):
    print(thing)

If you want the indices use enumerate. It attaches indices to each item so you can loop over both at the same time. No need for range or len.

# Forward over items, with indices
for i, thing in enumerate(things):
    print(i, thing)

# Backward over items, with indices
for i, thing in reversed(enumerate(things)):
    print(i, thing)
  • Related