Delete Starting Even Numbers - Loops


#1

https://www.codecademy.com/paths/computer-science/tracks/cspath-flow-data-iteration/modules/dspath-python-loops/lessons/python-functions-loops-cc/exercises/remove-even-nums

The question;

Write a function called delete_starting_evens() that has a parameter named lst .

The function should remove element from the front of lst until the front of the list is not even. The function should then return lst .

For example if lst started as [4, 8, 10, 11, 12, 15] , then delete_starting_evens(lst) should return [11, 12, 15] .

Make sure your function works even if every element in the list is even!

My code;

def delete_starting_evens(lst):
  for i in lst:
    if i % 2 == 0:
      lst = lst[1:]
  return lst

print(delete_starting_evens([4, 8, 10, 11, 12, 15])) #returns [12,15]
print(delete_starting_evens([4, 8, 10])) # returns []

My question: Why does 11 get removed from the first function call?


#2

It could be caused by mutating the list you are iterating over. That can often cause problems that we don’t foresee.

What if you found the first odd number and used its index?

>>> lst =  [4, 8, 10, 11, 12, 15]
>>> for i in range(len(lst)):
	if lst[i] % 2:
		break

	
>>> lst[i:]
[11, 12, 15]

.


#4

Thank you for the reply. I can’t get it to work but will keep trying.


#5

For your code to work properly you have to also add a break, because its a for loop, even if i isnt a even number anymore, it continues looping the list, therefore lst[1:] goes further than 11. Thats why a while loop is recommended for this exercise, it loops till i isnt even anymore and stops by himself. Hope you understand what I mean.

def delete_starting_evens(lst):
  for i in lst:
    if i % 2 == 0:
      lst = lst[1:]
    else:                      #if i % 2 != 0 it stops here and code works now correctly
      break
  return lst

print(delete_starting_evens([4, 8, 10, 11, 12, 15])) #now returns [11, 12,15]
print(delete_starting_evens([4, 8, 10])) # returns []

As an addition, thats my code for this, you can also use list.pop to get rid of the evens:

def delete_starting_evens(lst):
  while lst and lst[0] % 2 == 0:
    lst.pop(0)
  return lst

while lst returns true if lst isnt empty, if lst is empty at the end it returns false and the loop stops.


#6

Hi @lab-xi,

Your for loop iterates through the original list that is passed to the function.

Meanwhile, this statement creates a new list and assigns it to lst

      lst = lst[1:]

However, the for loop continues to iterate through the original list that was passed to it.

The following may illuminate the problem …

def delete_starting_evens(lst):
  position = 0
  for i in lst:
    print("\nTesting position in original list {:d} - Value: {:d}".format(position, i))
    if i % 2 == 0:
      print("{:d} is even - Getting rid of {:d}".format(i, lst[0]))
      lst = lst[1:]
      print("New list: {}".format(lst))
    position += 1
  return lst
print("******************************")
lst = [4, 8, 10, 11, 12, 15]
print(lst)
print(delete_starting_evens(lst))
print("******************************")
lst = [4, 8, 10]
print(lst)
print(delete_starting_evens(lst))
print("******************************")
lst = [4, 8, 10, 11, 12, 15]
print(lst)
print(delete_starting_evens(lst))
print("******************************")
lst = [4, 8, 10]
print(lst)
print(delete_starting_evens(lst))

Output …

******************************
[4, 8, 10, 11, 12, 15]

Testing position 0 in original list  - Value: 4
4 is even - Getting rid of 4
New list: [8, 10, 11, 12, 15]

Testing position 1 in original list - Value: 8
8 is even - Getting rid of 8
New list: [10, 11, 12, 15]

Testing position 2 in original list - Value: 10
10 is even - Getting rid of 10
New list: [11, 12, 15]

Testing position 3 in original list - Value: 11

Testing position 4 in original list - Value: 12
12 is even - Getting rid of 11
New list: [12, 15]

Testing position 5 in original list - Value: 15
[12, 15]
******************************
[4, 8, 10]

Testing position 0 in original list - Value: 4
4 is even - Getting rid of 4
New list: [8, 10]

Testing position 1 in original list - Value: 8
8 is even - Getting rid of 8
New list: [10]

Testing position 2 in original list - Value: 10
10 is even - Getting rid of 10
New list: []
[]

#7

Thank you for the reply - lists returning true/false when not empty/empty is a new trick for me!


#8

No trick, at all. There are no tricks in programming. Just logic which can be spun in many ways.

if lst:

In the above we draw upon the truthiness of the object. Empty objects are not truthy.

0
""
''
[]
{}
()
None

… are all falsy. Demonstrated another way, consider that and is short-circuited on False, so in the following, the first operand will be returned…

>>> () and True
()
>>> {} and True
{}
>>> [] and True
[]
>>> 0 and True
0
>>> '' and True
''
>>> "" and True
''
>>> None and True
>>> 

Notice that the last one has no output. That’s because None has no printable characters, so nothing is outputed, not even a newline.


#9

Thank you for the reply - I can see exactly what is happening with the code in my original post.

If there a way to modify a list passed into a function and have the function use the new modified list for the next iteration of the loop?


#10

Is this what you mean? …

def triple_the_numbers(nums):
    # triple all the numbers in the original list
    for i in range(len(nums)):
        nums[i] *= 3

my_numbers = [7, 4, 9, 8, -3]
triple_the_numbers(my_numbers)
print(my_numbers)

Output …

[21, 12, 27, 24, -9]

Note that the function modifies the original list that is passed to it.

You can also use append or other list methods to modify the original.


#11

Ok, so your original example with the break in the loop is still looping the original list, and modifying a new, separate list.

The difference with your code is that the loop is terminating once it reaches an odd number, and therefore not continuing to modify the new list by iterating through the original list. I think I’ve got it now(?). Thanks again!


#12

Quick question:

Can you elebaorate which part of your code is meant to “remove element from the front of lst until the front is odd?”

Is if i % 2 == 0:
lst = lst[1:] ?

Can you help me on that?


#13

Hi @micheledallari940840,

Yes the first line initiates the for loop.

The second line will check if the value at the index (i) currently in the loop is even.

Line 3 states that if it is an even number, lst should now equal lst with the first index (index 0) removed.

Lines 4 and 5 state that if the value of the number at the current index is not even, finish iterating the loop.

1  for i in lst:
2    if i % 2 == 0:
3      lst = lst[1:]
4    else:
5      break

#14

Clear! thanks @lab-xi