My pop function always skipping 8

: https://www.codecademy.com/courses/learn-python-3/lessons/python-functions-loops-cc/exercises/remove-even-nums?action=resume_content_item

I’m facing a weird problem in the lesson which lessons link I’ve put above. In here I have used .pop() function to remove first even numbers from my list but, I don’t know why it is always omitting the number 8. I have provided my code below.

#Write your function here
def delete_starting_evens(lst):
  i = 0;
  while i < len(lst):
    if(lst[i]%2 == 0):
      print("Popping %d"%(lst[i]));      
      lst.pop(0);
    else:
      print("Breaking");
      break;
    i += 1;
  return lst;

#Uncomment the lines below when your function is done
print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
print(delete_starting_evens([4, 8, 10]))
1 Like

Hi @abtahitajwar,

You are incrementing i with this statement at the end of every iteration of the loop:

    i += 1;

By the end of the first iteration, the 4 has been removed, and 8 has been shifted to index 0. You have incremented i to 1, so the 8 has escaped notice, and does not get removed.

Either reconsider when to execute the statement that increments i, or use a different approach to get past the starting even numbers.

Incidentally, you do not need a semicolon at the end of each line.

2 Likes

Now I am facing a different problem. My function is working fine by the problem is it is not popping the last element of the list and making it empty. At the second test input an empty string should be returned but it is not popping the last 10 after it is being an even number. Here is my code below.

#Write your function here
def delete_starting_evens(lst):
  i = 0;
  while i < len(lst):
    if(lst[0]%2 == 0):      
      print("Popping %d of index %d"%(lst[0], i));      
      lst.pop(0);
    else:
      print("Breaking");
      break;
    i += 1;
  return lst;

#Uncomment the lines below when your function is done
print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
print(delete_starting_evens([4, 8, 10]))
1 Like

this is because i = 2 while the length of the list is only 1 element long.

This problem exists because you are altering your list while you use it to check. Try copying the list and use this copy for altering instead. you could also store the length of the list in a variable before using it in the loop.

example:

listlength = len(lst)
	while i < listlength:

personally i find creating a copy of the original better practice tho. The original should never be altered in my opinion.

3 Likes

Oh yeah! I didn’t think that :stuck_out_tongue: Btw thanks :smiley:

2 Likes

This is driving me absolutely nuts: Why won’t my function delete the last 10 in the second function call?

#Write your function here
def delete_starting_evens(lst):
  for i in lst:
    if i%2==0:
      del lst[0]
  return lst

#Uncomment the lines below when your function is done
print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
print(delete_starting_evens([4, 8, 10]))

If you do something to change the length of a list in a for loop, you’ll likely get unexpected results. A for loop behaves as if it is implemented ‘beneath the hood’ by a while loop:

def delete_starting_evens(lst):
    i = 0
    while i < len(lst):
        if lst[i] % 2 == 0:
            del lst[0]
        i += 1
    return lst

print(delete_starting_evens([4, 8, 10]))
# Output:
[10]

You can see that, once two elements have been removed, i has been incremented to 2, and is now longer than len([10]).

Take-home lesson: Do not change the length of a list over which you are iterating. Sometimes you can get away with it, but you’ll frequently see unexpected results. (It’s OK, though, to change - mutate - list elements: just do not delete them.)

I am not sure if i agree with this. It might be fine if you are absolutely sure you don’t need the data anymore. But if you need the original data again your data would not be correct since it has been modified.

I think it would be much better to create a copy of the input. You than can alter the copy and send this copy back when done. This way you can be sure the data that is put in is not changed and if needed can be reused.

1 Like

Well, that is a matter that depends upon the purpose and design of your script. You certainly must decide whether the original list is to be preserved, and code accorgingly, but it is equally certainly accepted practice in appropriate contexts to code a function or method that “does something but returns None,” that is, one that mutates a list passed as an argument.

1 Like