Skip to content Skip to sidebar Skip to footer

Why Wasn't The Last Number In That List Removed?

This is my Python program: def highest_even(li): for num in li: if num % 2 != 0: li.remove(num) return li print(highest_even([10,2,3,4,5,80,15,99])) And the output

Solution 1:

It's generally a bad idea to modify a list that you're iterating over, all sorts of strange things can happen. The particular strange thing that's happening here has to do with the way Python iterates over lists.

Think of Python maintaining the position of the current item for iterating. When you delete an item, the others all shift "left" in the list but Python still advances the position. That means, if you have two odd numbers in a row (like 15 and 99), deleting the 15 moves 99 to the left (to where the 15 was) but the next iteration will be looking at where the 99 was before shifting, not where it is now.

For example, consider the list [1, 3, 6, 8], these are the steps Python will take:

List          Pos  newList    newPos  comment
----          ---  -------    ------  -------
[1, 3, 6, 8]0[3, 6, 8]1    Odd 1, delete, advance.
[3, 6, 8]1[3, 6, 8]2    Even 6, leave, advance.
[3, 6, 8]2[3, 6, 8]3    Even 8, leave, advance.
[3, 6, 8]3                      iteration finished.

You can see that consecutive odd numbers cause a problem here, it will only delete alternate ones.

As to the solution: if, as your code suggests, you just want the even numbers in the list, you can use the much more succinct (and Pythonic) list comprehension (no need even for a function to do this):

myList = [10, 2, 3, 4, 5, 80, 15, 99]
evens = [item for item in myList if item % 2 == 0]
# gives [10, 2, 4, 80]

And, for completeness, since your function name seems to indicate you want the highest even number, that would be something like:

biggestEven = max([item for item in myList if item % 2 == 0])
# gives 80

Your problem actually has nothing to do with the fact the 99 is at the end of the list, any consecutive odd numbers, anywhere in the list, would cause the same issue.

Solution 2:

do not modify a list you iterate in

you can copy before iterate on

def highest_even(li):
  for num in li.copy():
    if num % 2 != 0:
      li.remove(num)
  return li

print(highest_even([10,2,3,4,5,80,15,99]))

Execution :

[10, 2, 4, 80]

Solution 3:

As so many comments mention: it's unsafe (or at least it presents some unexpected behavior) to modify a list as you iterate over it. The usual fix here for lists that aren't giant is simply to copy the list when you go to iterate on it.

for num in li[:]:
   # everything as before

That little slice syntax makes Python take the list li, create a new list of its entire contents, and iterate over that, instead. Now since you're removing things from li, but iterating over the copy of li made by slicing it, there's no issue.

Solution 4:

this is because of you iterated through the list while editing it.

only_even= []
for n in lst:ifnotn%2:only_even.append(n)

other methods

only_even = [n for n in lst if not n % 2]
only_even = list(filter(lambda x: not n % 2, lst))

Solution 5:

You should never update the data structure you are iterating in, to maintain the invariants of the loops.

If you print the li, and num right after the for num in li:, you'll see that after you remove the element from the list, the next element is skipped, meaning that the indexed is moved forward, same thing happens to 99 element.

You can check it here.

defhighest_even(li):
  for num in li:
    print(li, num)
    if num % 2 != 0:
      li.remove(num)
return li

gives the output:

In[3]: highest_even([10,2,3,4,5,80,15,99])
([10, 2, 3, 4, 5, 80, 15, 99], 10)
([10, 2, 3, 4, 5, 80, 15, 99], 2)
([10, 2, 3, 4, 5, 80, 15, 99], 3)
([10, 2, 4, 5, 80, 15, 99], 5)
([10, 2, 4, 80, 15, 99], 15)
Out[3]: [10, 2, 4, 80, 99]

Post a Comment for "Why Wasn't The Last Number In That List Removed?"