0

Basically I want the user to input a number, that then scans the words in a list that are imported from dictionary.txt. It then deletes any word that's length is equal to the users input and then updates the list outside of the function.

def read_and_delete(x):
        count = 0
        i = 0
        for delete in x:
            if x[i] != word_length:
                del x[i]
                i += 1
                return
            elif x[i] == word_length:
                count += 1
                i += 1
                return
            else:
                break
        print(len(list_of_words))

word_length = int(input("Please enter a word length: "))
dictionary = open("dictionary.txt", "r")
list_of_words = [word.rstrip('\n').rstrip('\r') for word in dictionary]
read_and_delete(list_of_words)
MLJezus
  • 79
  • 1
  • 9

6 Answers6

2

First of all, I want to review the function you already have:

def read_and_delete(x):
    count = 0
    i = 0

    # for each word in list, store word in the "delete" variable
    for delete in x:

        # you are iterating over elements, but also using index
        if x[i] != word_length:  # if word not equals length
            del x[i]
            i += 1
            return  # exit from function

        elif x[i] == word_length:  # again, comparing a word and a number
            count += 1
            i += 1
            return  # exit from function
        else:  # never happens, because word is either
               # equal or not, there is no other case
            break  # exit from loop
    # if we actually visited the for loop (the list was not empty),
    # this line would never be executed
    print(len(list_of_words))

Next, how to fix it:

  1. If you want to iterate over all list, you should not use return or break (these are useful in other cases, thought).
  2. If you do want to remove elements from a list, you should do that a bit differently: How to remove list elements in a for loop in Python?
  3. To get length of the word (and any other string) you can use len().
  4. Also, check the logic of your conditions.

To summarize, here's the fixed function (makes a new list):

def read_and_delete(x):
    result = []

    for word in x:
        if len(word) != word_length:
            result.append(word)  # add word to the end of "result"

    print(len(result))

As you can see, the loop is pretty simple now. So, you can rewrite it as a list comprehension:

# instead of function call
filtered_list = [word for word in list_of_words if len(word) != word_length]
print(len(filtered_list))

You can read that as:

[word                          # put each "word" into a list
 for word in list_of_words     # get them from "list_of_words"
 if len(word) != word_length]  # leave only those which length != "word_length"

Edit: fixed condition in the function.

Community
  • 1
  • 1
Meloman
  • 104
  • 1
  • 7
1

Assuming that your dictionary.txt lists one word per line:

word_length = int(input("Please enter a word length: "))

with open("dictionary.txt", "r", encoding="utf-8") as word_list:
    words = [line.strip() for line in word_list if len(line.strip()) != word_length]

print("%i words remain" % len(words))
print(words)

The idea is not to make a list and then delete items from it in a separate step, but to filter the items while we are building the list.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • all the words are on individual lines, I should of mentioned that – MLJezus May 14 '17 at 07:19
  • So the above should work (In the future, always include a sample of your input in your question. Write the question in such a way that someone with *no context at all* has all the necessary information.) – Tomalak May 14 '17 at 07:20
1

you can use built-in 'filter' function:

ls = ['word1','word','w0']
len_delete = 4
new_ls = filter(lambda x:len(x)!=len_delete,ls)

new_ls = ['word1', 'w0']

brc
  • 249
  • 2
  • 6
0
def read_and_delete(x):
    resulting_list = []          
    for delete in x:
        if len(delete) == word_length: # len(delete) returns length of element
            continue  # goes to the next element in the list                             
        else:
            resulting_list.append(delete)             
    print(resulting_list)

word_length = int(input("Please enter a word length: "))
dictionary = open("dictionary.txt", "r")
list_of_words = [word.rstrip('\n').rstrip('\r') for word in dictionary]
read_and_delete(list_of_words)

P.s. study more about how loops work :)

techkuz
  • 3,608
  • 5
  • 34
  • 62
  • 1
    Why use `enumerate` in this code? Surely `for delete in x` would work. – Rolf of Saxony May 14 '17 at 07:39
  • @RolfofSaxony you are right. Thanks for the hint. I was re-writing original code and there were 'count' and 'i' variables. I switched it to enumerate and after other changes did not realize that they are unnecessary anymore. – techkuz May 14 '17 at 07:43
0

I think you come from a C perspective or a similar language:

def read_and_delete(x):
    for ix, delete in enumerate(x):
        if len(delete) == word_length:
            del x[ix]

    return x

word_length = int(input("Please enter a word length: "))
dictionary = open("dictionary.txt", "r")
list_of_words = [word.rstrip('\n').rstrip('\r') for word in dictionary]
read_and_delete(list_of_words)
print(list_of_words)

This newer version of your code will update the list in-place and therefore any change made inside read_and_delete for x--the passed list to the function, will affect all references of that list including list_of_words. This function also returns the affected list, however you can easily remove it because list_of_words gets updated by any change made to it inside the function. Of course, there is an easier way to achieve this in Python, for clarity I went with your code so not to puzzle you.

Edit: Thanks to @RolfofSaxony for pointing out the ambiguity in the above code, as I result I've edited this question to address the problem:

word_length = int(input("Please enter a word length: "))
dictionary = open("dictionary.txt", "r")
list_of_words = [word.rstrip('\n').rstrip('\r') for word in dictionary]

def read_and_delete(x):
    for delete in x[:]:
        if len(delete) == word_length:
            ix = x.index(delete)
            del x[ix]
    return x


read_and_delete(list_of_words)
print(list_of_words)
GIZ
  • 4,409
  • 1
  • 24
  • 43
  • 1
    You're modifying the list while you iterate over it, it will fail! http://stackoverflow.com/questions/6260089/strange-result-when-removing-item-from-a-list – Rolf of Saxony May 14 '17 at 07:54
  • @ Rolf of Saxony Thanks for pointing that out. I never thought about it. I'll edit my question. – GIZ May 14 '17 at 09:30
0

My sixpences worth:

def read_and_delete(x,word_length):
    x = [elem for elem in x if len(elem) !=word_length]
    return x

a=['123','1234','123','123','abcdef','abc','1234']
a=read_and_delete(a,3)
a
['1234', 'abcdef', '1234']

Sorry @Meloman! Just seen your post, which I virtually replicate and with considerably less explanation.

Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60