In the context of this exercise, using a for loop to iterate through the list seems like a good solution. However this ends up generating wrong solutions, why doesn’t this work?
To understand why for iteration breaks in this lesson we need to break down what happens as the list runs:
lst = [4, 8, 10, 11, 12, 15]
for i in lst:
This code will let us take a look at how the code breaks down as it iterates through the list. So the results will be:
[8,10,11,12,15] #i = 4 (index 0)
[10,11,12,15] #i = 10 (index 1 above)
[11,12,15] #i = 12(index 2 above)
#the loop will stop at this point, as there is no index 3
So because the list is shifted each time it runs, an element will be skipped with each pass and cause it to stop. In our example we would have expected to empty the list by the end but that was not the case. To give a hint regarding the code challenge, since for doesn’t work if the list changes, what if you used while? What kind of conditions would you be looking to maintain while moving through the list?
Feel free to discuss below and help each other with understanding this concept!
Modifying the list will interfere with the loop. You move elements when you remove at the front, while at the same time the loop progresses forwards.
Also, all that moving makes it very inefficent. If you reversed it first, then you could pop until the last value is no longer even. Popping is fast and the loop wouldn’t be affected (however you should not use a for-loop because that doesn’t match what you’re doing, which is repeating something until a condition’s outcome changes)
I used a similar coding scheme (see below) and mine didn’t iterate past the first variable - not sure why.
@ionatan Sorry but I don’t understand your answer. How is this code modifying the list in a way that different then the .pop() command? Also, what do you mean by reversed first?
Finally, could you write:
while len(lst) and lst % 2 == 0:
My code attempt:
#Write your function here
for nums in lst:
if len(lst) >= 0 and lst % 2 == 0:
while lst % 2 == 0:
return 'NO DICE'
#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]))
print(delete_starting_evens([7, 8, 10]))
Ok to clarify the second block of code was my first attempt at defining the function. The first block was my attempt to rewrite the solution from memory (which I also managed to screw up).
The FOR operation was just so that the function would run through each individual item in LST. Then in each element IF len(lst) is >0 and odd remove index 0 WHILE LST is odd. I thought it made sense.
The ELSE item was just to give the function something to return that indicated the string did not begin with an even number.
The list.pop() method will raise an exception if list length is zero.
if len(lst) > 0
The use of a while loop inside a for loop can be a tricky thing to manage, but first we should determine if that much logic is even needed. What is the most we need to iterate the list one time?
Answer: A single loop.
As for the textual return, that would never be advisable if the return is expected to be a list. It would be feeding garbage back to the caller and raise an exception as soon as a list method was called on that object. It would certainly be messing up the data, nonetheless.
>>> a = "string"
>>> b = a.copy()
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
b = a.copy()
AttributeError: 'str' object has no attribute 'copy'
>>> b = list(a).copy()
['s', 't', 'r', 'i', 'n', 'g']
Here is a list of list methods and built in functions that work on lists, and perhaps other object types, as well.
Python List append()
Add Single Element to The List
Python List extend()
Add Elements of a List to Another List
Python List insert()
Inserts Element to The List
Python List remove()
Removes Element from the List
Python List index()
returns smallest index of element in list
Python List count()
returns occurrences of element in a list
Python List pop()
Removes Element at Given Index
Python List reverse()
Reverses a List
Python List sort()
sorts elements of a list
Python List copy()
Returns Shallow Copy of a List
Python List clear()
Removes all Items from the List
Checks if any Element of an Iterable is True
returns true when all elements in iterable is true
When i is a positional element and we pop that element, all the elements to the right of that get shifted. The next element to be iterated in the list will be from one more to the right that it was expected to be, hence an element is skipped.
4, 8, 10 # i is 4
8, 10 # i is 10
10 # i is None
The iterator moves forwards, same as ever.
You’re moving the values.
Also, you probably don’t want to pop at the front of the list. Do it at the back instead so that you don’t need to move all the other values every time.
(similarly you’re not going to want to copy all-but-the-first every iteration, better to find out where to slice, and then do it once)
…Except that there’s no need to modify the original, the simpler approach is to create a new list with the values to keep.
I guess a lot of people have issues with the ways to solve this exercise. I have used all methods to test my knowledge and all worked: lst[1:], del, lst.remove(), but can not get my peace with .pop() method in for loop as the previous user had issue (it worked in while loop!).
It works in the following code:
for number in lst:
if number % 2 == 0:
print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
# prints: [11, 12, 15]
but here doesn’t return an empty list as it supposed to:
Thank you @mtf for your input - I have used while loop earlier and it worked for me. I was just puzzled why .pop() works in one instance and does not work in another (I would be OK to know if it would not work at all, but it does in the first lst example). When you are a beginner, such things just fry your brain
The key is to keep note of the pointer of a for loop. Think in terms of next being loaded with the index following when reaching the current element, and it does not change when the list is shifted to the left.