[Tutor] trouble with list.remove() loop
Hello all, I am currently trying to write a program which can find the solution to a game of hangman. In a part of the program, a user inputs a letter, a tester tells him if the word contains that letter, and then if the answer is no, all words containing that letter are removed from the list of remaining candidates. However, the code I've written seems to remove some, but not all the words containing the letter. Strangely though, if i run it a few more times it gets some of the ones it missed the 1st time round, untill after enough iterations it gets all of them. I cant understand why it doesnt remove all of them the first time round. I have cut the offending code and formatted it to work on its own, and also to fit into a relatively short email. # A sample list of words, one of which is the answer. candidates = [abacus,amazing, ozimandias, a,alphanumeric, functioning] # In the following code, the user has guessed the letter 'a', # and the tester has told him that the letter 'a' is not in the word. user_guess=a tester_response=no # The following code should eliminate all words which contain the letter # 'a', leaving only the word 'functioning' in the list if tester_response in (No,no,n,N,NO): for word in candidates: if user_guess in word: print word, removed.. candidates.remove(word) print candidates Running once gives this output abacus removed.. ozimandias removed.. alphanumeric removed.. ['amazing', 'a', 'functioning'] But if i run it again it successfully removes 'amazing, and the next time it removes 'a', leaving the correct answer. I'm perplexed by this strange behaviour and would be most appreciative of any help. I'm very new to python so apologies for any formatting/style errors, and also for the simplicity of the problem. Best regards Dave ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] trouble with list.remove() loop
On 25/09/2010 20:44, D Ryan (2) wrote: Hello all, I am currently trying to write a program which can find the solution to a game of hangman. In a part of the program, a user inputs a letter, a tester tells him if the word contains that letter, and then if the answer is no, all words containing that letter are removed from the list of remaining candidates. However, the code I've written seems to remove some, but not all the words containing the letter. Strangely though, if i run it a few more times it gets some of the ones it missed the 1st time round, untill after enough iterations it gets all of them. I cant understand why it doesnt remove all of them the first time round. I have cut the offending code and formatted it to work on its own, and also to fit into a relatively short email. # A sample list of words, one of which is the answer. candidates = [abacus,amazing, ozimandias, a,alphanumeric, functioning] # In the following code, the user has guessed the letter 'a', # and the tester has told him that the letter 'a' is not in the word. user_guess=a tester_response=no # The following code should eliminate all words which contain the letter # 'a', leaving only the word 'functioning' in the list if tester_response in (No,no,n,N,NO): for word in candidates: if user_guess in word: print word, removed.. candidates.remove(word) print candidates Running once gives this output abacus removed.. ozimandias removed.. alphanumeric removed.. ['amazing', 'a', 'functioning'] But if i run it again it successfully removes 'amazing, and the next time it removes 'a', leaving the correct answer. I'm perplexed by this strange behaviour and would be most appreciative of any help. I'm very new to python so apologies for any formatting/style errors, and also for the simplicity of the problem. Best regards Dave ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor You are mutating the list that you are iterating over so in essence you are looking at the word in list index 0, testing it, and removing it, then moving onto list index 1 but now your list has 'amazing' in index 0 so that does not get checked. The simplest way is to iterate through a new list with this for word in candidates[:]: That will create a new list that you will iterate over while you mutate the original list. -- Kind Regards, Christian Witts ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] trouble with list.remove() loop
On Tue, 28 Sep 2010 06:55:15 pm Christian Witts wrote: You are mutating the list that you are iterating over so in essence you are looking at the word in list index 0, testing it, and removing it, then moving onto list index 1 but now your list has 'amazing' in index 0 so that does not get checked. The simplest way is to iterate through a new list with this for word in candidates[:]: That will create a new list that you will iterate over while you mutate the original list. Another technique is to iterate over the list backwards, so you are only ever deleting words you've already seen: for i in range(len(candidates)-1, -1, -1)): word = candidates[i] if some_test(): del candidates[i] I know the series of -1, -1, -1 is ugly, but that's what it takes. -- Steven D'Aprano ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] trouble with list.remove() loop
D Ryan (2) wrote: Hello all, I am currently trying to write a program which can find the solution to a game of hangman. In a part of the program, a user inputs a letter, a tester tells him if the word contains that letter, and then if the answer is no, all words containing that letter are removed from the list of remaining candidates. However, the code I've written seems to remove some, but not all the words containing the letter. Strangely though, if i run it a few more times it gets some of the ones it missed the 1st time round, untill after enough iterations it gets all of them. I cant understand why it doesnt remove all of them the first time round. I have cut the offending code and formatted it to work on its own, and also to fit into a relatively short email. # A sample list of words, one of which is the answer. candidates = [abacus,amazing, ozimandias, a,alphanumeric, functioning] # In the following code, the user has guessed the letter 'a', # and the tester has told him that the letter 'a' is not in the word. user_guess=a tester_response=no # The following code should eliminate all words which contain the letter # 'a', leaving only the word 'functioning' in the list if tester_response in (No,no,n,N,NO): for word in candidates: if user_guess in word: print word, removed.. candidates.remove(word) print candidates Running once gives this output abacus removed.. ozimandias removed.. alphanumeric removed.. ['amazing', 'a', 'functioning'] But if i run it again it successfully removes 'amazing, and the next time it removes 'a', leaving the correct answer. I'm perplexed by this strange behaviour and would be most appreciative of any help. I'm very new to python so apologies for any formatting/style errors, and also for the simplicity of the problem. I'd like to point out a robust method to avoid such pitfalls: create a new list instead of modifying the old one: old_candidates = candidates candidates = [] for word in old_candidates: if user_guess in word: print word, removed else: candidates.append(word) print candidates Often you can simplify that to a list comprehension like candidates = [word for word in candidates if user_guess not in word] Peter ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor