Why Wasn't The Last Number In That List Removed?
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?"