Having difficulty popping last value to display an empty list or odd numbers only

I’ve been tasked with the following:

Write a function called delete_starting_evens() that has a parameter named lst .The function should remove elements 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!

And I’m so close. I have two loops written, here is the first:

#Write your function here

def delete_starting_evens(lst):
  lst = [lst.pop(0) for i in lst if i % 1 == 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]))

This only displays the even numbers for some reason even though I want to pop out the odd numbers “i% 1 == 0”.

My other is:

#Write your function here

def delete_starting_evens(lst):
  for i in lst:
    if i % 2 == 0:
      lst.pop(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]))

In the second print it is leaving the 10 and not deleting out the entirety of the list. Not sure why the 10 is there because it is even.

Hello @jrb0831!

Using .pop() returns the value that you just removed from a list, meaning your first function creates a list of all the numbers you have popped off. Additionally, using i % 1 == 0 as your condition makes it true for every element in the list. I think you meant to use i % 2 == 0. This also iterates through every element in lst when you only want to iterate through each element from the beginning until you get to an odd number.

For the second function, I’m not completely sure what is happening, but it might have something to do with the fact that you’re trying to iterate over lst while you are removing elements from it. Maybe a more experienced user can confirm this.

3 Likes

@dr_victoria

Thanks for the pop explanation. I thought that i % 1 == 0 would pull back an odd number but I guess that’s incorrect. Do you know if i % 2 == 1 would work? I guess I’m trying to determine “if” a number is odd, then pop out that value.

1 Like

@dr_victoria

Okay update. I was able to delete all even numbers that are in list which was a huge step. Now I need to see how I can only delete the even numbers until I see the first odd number, then return the rest of the list regardless of odd/even.

#Write your function here

def delete_starting_evens(lst):
  lst = [i for i in lst if i % 2 != 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]))
1 Like

I am having trouble figuring out how to return the rest of the list once I reach my first odd number. I have my if statement but I’m wondering what I’m missing.

If i is odd, then return the rest of the list. I’m wondering what syntax this might be. Maybe I need to restructure my list comprehension.

Yes, i % 2 == 1 would work to identify odd numbers. Great work on removing the even numbers!

Remember that you can use lst[start:end], with start being the starting index and end being one more index than the index of the last element returned, to return parts of lists. You could implement this, along with a for loop and if statement (no list comprehension) to eliminate only the starting even numbers.

2 Likes

You’re using list comprehensions pretty well. I

In addition to @dr_victoria’s method (which works very well), you can consider this:

If you need to break the loop, you might as well write it in a for-loop so you can have multiple conditionals, and when you hit an odd number call for a break or even better, simply return.

It’s good to get a sense of the different options. There might be only one “best” option for this case, but the other ones might serve you well in a tangentially similar scenario.

One thing you can think about when having multiple possible answers is: what runs the least code? what takes up the least space? Even if it seems trivial here, what seems like a small difference can quickly take much larger proportions when scaled up. If you can think about it logically at this level, then when the complexity increases you will have better tools with which to clarify things.

3 Likes

Thank you @toastedpitabread

Should the break simply end the cycle through the list?

I’ve written this, expecting that once it hits the first odd number it breaks the loop and returns the rest of the list.

#Write your function here

def delete_starting_evens(lst):
  for i in lst:
    if i % 2 == 1:
      break
    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]))

@dr_victoria

You could implement this, along with a for loop and if statement (no list comprehension) to eliminate only the starting even numbers.

Would this include any series of numbers that were in the call to the function? I believe this would work if you knew the numbers in the call but it wouldn’t work if you did not know what values would be called.

This would work with any function input, although it would return None for an input that consisted only of even numbers. You would need an additional conditional statement if you wanted to return an empty list instead of None.

1 Like

del in a for loop is an invitation to problems.

>>> f = delete_starting_evens
>>> f([])
[]
>>> f([10, 12, 14, 16, 18, 20])
[16, 18, 20]
>>> 
2 Likes

I’m not sure I understand the context of your second statement f = delete_starting_evens. Is this in relation to the del lst[0] being problematic or is this a hint towards the solution of the problem?

This is in relation to del being problematic when used in for loops. Because the number of elements in the list is constantly changing, using a for loop to delete elements one by one would cause unexpected results.

Here, @mtf demonstrates that, even though 16, 18, and 20 are even, they are not removed because of the use of del in a for loop.

1 Like
>>> f = delete_starting_evens

That line assigns a reference to the function with the long name. Now we can run that function using only the short name, f.

1 Like

But in theory it should work right. All those numbers are even, why wouldn’t it delete them all? Why is it only deleting the first 3?

Since I can’t use del or pop, is my only option [start:end]? That’s hard for me to comprehend because the start and end of the list will change constantly.

A for loop is fixed and when we delete elements, others are skipped.

2 Likes

Using del in a for loop wouldn’t remove all the even numbers because the for i in lst: statement iterates over each element in the list. With elements being deleted as the loop executes, the loop simply won’t iterate over all the elements. What @mtf said.

Instead of using [start:end] each time you encounter an even number, why not try only using it once? In other words, try using [start:end] when you get to an odd number and not for each even number.

1 Like

How will the loop know to return the rest of the list using [start:end]?

So if it’s odd, then I want it to return the rest of the list regardless. I’m thinking something like [i:-1] where i is the current number in the loop (could be odd) and -1 is the final element in the index of the list.

#Write your function here

def delete_starting_evens(lst):
  for i in lst:
    if i % 2 != 0:
      lst[i:-1]
      break
  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]))

The name given this function is suggestive, and sends some people down the road of del. However, there is an inverse. Consider probability.

P(E)

and,

P(NOT E) = 1 - P(E)

It makes perfect sense to look for the first odd, and forget about deleting. Just take a slice from the current position.

is P a list in this scenario and E is the element in the list?