0

I am attempting to write a little program to play the popular game, Wordle.

One of my function attempts to remove words from a word bank which do not contain a particular letter. The function does a decent job, but I have discovered that the function occasionally fails to identify words that should be removed from the list. If I call on the function repeatedly, it will eventually eliminate all the correct words.

#Creates a list of 4266 five-letter words from a text file
five_letters = open("five.txt", "r")
five = five_letters.read()
five = five.split()

#Iterates across list and removes words that do not contain a particular letter
def eliminate_words_not_containing(list, letter):
    for word in list:
        if letter not in word:
            list.remove(word)
    return list

# Call on the function 10 times and print the length of the list after each call
print(len(five))
for i in range(10):
    five = eliminate_words_not_containing(five, "e")
    print(len(five))

The output is:

4266
2932
2319
2070
2014
2010
2010
2010
2010
2010
2010

How can I write the function so that it catches all the words that do not containing a particular letter the first time through?

Silly question: Is it possible for the program to be running too quickly, and it skips over words?

Yin
  • 3
  • 1
  • Don't remove things from a list while you're iterating over it. – user2357112 Feb 07 '22 at 19:20
  • The problem you are running into is that you are mutating the list of words as you are iterating over it. See this answer: https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating – James Feb 07 '22 at 19:20
  • Do not iterate over mutable collections while simultaneously removing elements from them. Refer [this](https://docs.python.org/3.1/tutorial/controlflow.html#for-statements). – Nikhil Kumar Feb 07 '22 at 19:20
  • "_Is it possible for the program to be running too quickly, and it skips over words?_" No. – takendarkk Feb 07 '22 at 19:20
  • Don't use `list` as a variable name, since Python uses that as the name of its constructor for a list. – jjramsey Feb 07 '22 at 19:21
  • Thank you to everyone who responded. I appreciate your help. – Yin Feb 07 '22 at 19:24

2 Answers2

0

You iterating over the original list, so when you remove one word the position isn't updated, try to make a copy of the list and iterate over it.

Edit: I'd try list comprehension if it was me so:

list = [word for word in list if letter not in word]
0

Because you are modifying your list while you are iterating over it, you are skipping words.

If your list is ['word1', 'word2', 'word3'] and you call your eliminate function, you will be left with ['word2'] because you removed 'word1', then your for loop moved on to the 2nd index, which is now 'word3' from the original list (with 'word2' being the first word in the list after the removal of 'word1').


There are several ways to solve the problem, but one solution would be to remember the indices to remove:

def eliminate_words_not_containing(word_list, letter):
    to_remove = set()
    for i, word in enumerate(word_list):
        if letter not in word:
            to_remove.add(i)
    return [word for i, word in enumerate(word_list) if i not in to_remove]

Probably just a regular list comprehension would be better in this case, but the above would be generalized in case you want to do something more complicated with each entry.


(Also, it's not good practice to use the variable named list because it clobbers the built-in type list in python.)

Stephen C
  • 1,966
  • 1
  • 16
  • 30