problem Deleting list items in a for loop (python)
Solution 1
The below code will fix your issue. You have to iterate over a copy of the list. You can't remove items from the list you are iterating over.
import copy
def main():
titles_list = ["English", "Math", "History", "IT", "Biology", "Spanish"]
titles_list_orig = copy.deepcopy(titles_list)
for title in titles_list_orig:
print "Do you want to keep the title:", title , "\n or Delete it? Input Y for keep, N for Delete "
Question = raw_input()
if str(Question.upper()) == "N":
titles_list.remove(title)
print titles_list
Solution 2
Your code actually has two major issues.
The first is that you are not calling the upper
method, but merely referencing it. You need to actually call it (via Question.upper()
) as w00t does in his answer.
Putting some diagnostic print statements inside your loop would have been a good way to see that (especially printing out str(Question.upper)
) (Tangent: Question
is a bad name for a variable that holds the answer to a question the program asked of the user)
Secondly, removing already seen items from a list you're iterating over will result in skipping values. You don't actually need to copy the whole list to deal with that - just iterating over it in reverse is enough to fix the problem.
Finally, a couple of minor cosmetic points are that raw_input()
accepts a prompt argument, so you don't need a separate print statement and calling upper()
on a string will itself always return a string:
titles_list = ["English", "Math", "History", "IT", "Biology", "Spanish"]
prompt = ("Do you want to keep the title: {}\n"
"or Delete it? Input Y for keep, N for Delete: ")
for title in reversed(titles_list):
answer = raw_input(prompt.format(title))
if answer.upper() == "N":
titles_list.remove(title)
print titles_list
Solution 3
I think the main issue in your code was incorrect usage of upper function. Once you fix it, you can remove the titles from the list as you please. You can either use index or the value. Here is the code snipped that worked for me
#!/usr/bin/python import string titles_list = ["English", "Math", "Biology", "IT", "History"] for title in titles_list: answer = raw_input("Do you want to keep this title %s, type y or n\n" % (title)) if string.upper(answer) == "N": # i = titles_list.index(title) # del titles_list[i] titles_list.remove(title) print "now list is" , titles_list print titles_list
Please see the commented lines using index. Also, you can make your code more concise using the raw_input(prompt) feature.
You also need to think about the scenario where there are multiple occurrences of the same titles in your list, in that case I suggest get all the indices for the title till the list is empty and delete the titles using del(index) as the solutions presented above will remove only the first occurrence of the title.
Solution 4
I know there is an answer already, here is another way for completeness, and to demonstrate list comprehension.
This method takes a list, asks to keep each item, and returns a new list excluding the ones marked for deletion:
def delete_items(titles):
deleted_items = []
for title in titles:
print('keep %s?' % title)
if str(raw_input().upper()) == 'N':
deleted_items.append(title)
return [e for e in titles if e not in deleted_items]
Related videos on Youtube
Comments
-
RY4N almost 2 years
Possible Duplicate:
Remove items from a list while iterating in PythonHi im having a problem i cant seem to delete items whilst iterating through a list in python, Here is what i've got: a title should be removed if a user Inputs n or N when asked the question to delete in the for loop, the problem is that when its all done the items are all still there and none have been removed...
titles_list = ["English", "Math", "History", "IT", "Biology", "Spanish"] for title in titles_list: print "Do you want to keep the title:", title , "\n or Delete it ? Input Y for keep, N for Delete " Question = raw_input() if str(Question.upper) == "N": titles_list.remove(title) print titles_list
-
RY4N about 13 yearsthanks :D i used splice cause its less lines but u lead me to needing to copy it thanks
-
ncoghlan about 13 yearsNo need to copy it, just iterate over it in reverse so the removals don't affect the items you see while iterating.
-
Sumod about 13 years@ncoghlan - can you please elaborate on your answer. not clear to me.
-
Wang Dingwei about 13 yearsYou might want to mention that new style string formatting only works in python 2.7 and later.
-
Richard Stagg about 13 yearsalternative to deepcopy, you can also use
orig = list(titles)
to copy a list :-) -
Steve Jessop about 13 years@Wesley: agreed, in fact that's more appropriate in general (i.e. for things other than strings), since it's a shallow copy rather than a deep copy. We don't need copies of the contents of
titles_list
. -
ncoghlan about 13 yearsIt's actually available in 2.6 or later
-
ncoghlan about 13 years@Sumod I elaborated on it a little more in my own answer.
-
ncoghlan about 13 yearsBut yeah, if you need to use 2.5 or earlier, then the
{}
in the format string needs to be replaced with a%s
and the formatting command itself becomesprompt % title
. -
ncoghlan about 13 yearsNo need to use the
string
module -answer.upper()
works just fine. However, did you actually try this and see what happens when you pressn
every time? You won't be offered a chance to remove"Math"
or"IT"
from the list. -
Morg. almost 11 yearsncoghlan. nice way to run around the python design
-
domokun about 10 yearsWhy would you manually copy the list when you can already cycle over a copy with
for title in titles_list[:]
?