-1

I am doing a task for school in a beginner Python course that requires a function which removes all the words that are in capital letters using the string method isupper() and gives a new list as an output, which includes only the words that are not in all caps, for example:

List given:

my_list = ["ABC", "def", "UPPER", "ANOTHERUPPER", "lower", "another lower", "Capitalized"]

Expected output:

['def', 'lower', 'another lower', 'Capitalized']

This is what i currently have:

def no_shouting(my_list):
    for word in my_list:
        if word.isupper() == True:
            my_list.remove(word)
    return my_list
if __name__ == "__main__":
    my_list = ["ABC", "def", "UPPER", "ANOTHERUPPER", "lower", "another lower", "Capitalized"]
    pruned_list = no_shouting(my_list)
    print(pruned_list)

Even though everything is seemingly fine to my rookie eyes, here is what my code gives as an output:

['def', 'ANOTHERUPPER', 'lower', 'another lower', 'Capitalized']

So for some reason, it does not remove the word "ANOTHERUPPER", but it removes every other uppercase word. How can I fix this?

  • 1
    Does this answer your question? [Strange result when removing item from a list while iterating over it](https://stackoverflow.com/questions/6260089/strange-result-when-removing-item-from-a-list-while-iterating-over-it) – Holloway Nov 21 '22 at 13:20
  • Oh, i see. I checked out the question @Holloway added but I still can't seem to wrap my mind around on how am I supposed to solve this issue, as we have not used e.g. `enumerate` yet in our classes so I doubt I'm allowed to use a technique like that on this. – ssaaradd Nov 21 '22 at 13:57

1 Answers1

0

As Holloway said "you're modifying the list as you're iterating through it". You should avoid mutating collection. To achieve what you want, you are basically writing the filter function. Instead of creating a new tool, why not use the right existing tool for the job? Here is how:

if __name__ == "__main__":
    my_list = ["ABC", "def", "UPPER", "ANOTHERUPPER", "lower", "another lower", "Capitalized"]
    pruned_list = list(filter(lambda word : not(word.isupper()), my_list))
    print(pruned_list)

or without the lambda keyword

def isNotUpper(word):
    return not(word.isupper())

if __name__ == "__main__":
    my_list = ["ABC", "def", "UPPER", "ANOTHERUPPER", "lower", "another lower", "Capitalized"]
    pruned_list = list(filter(isNotUpper, my_list))
    print(pruned_list)

output

['def', 'lower', 'another lower', 'Capitalized']

or more exactly you are doing a filterfalse:

import itertools 

if __name__ == "__main__":
    my_list = ["ABC", "def", "UPPER", "ANOTHERUPPER", "lower", "another lower", "Capitalized"]
    pruned_list = list(itertools.filterfalse(str.isupper, my_list))
    print(pruned_list)

source

aloisdg
  • 22,270
  • 6
  • 85
  • 105
  • 1
    Or `filterfalse(str.isupper, my_list)` – Kelly Bundy Nov 21 '22 at 13:33
  • This seems to be working, but I am not "allowed" to use `lambda` etc. as we have not yet been taught those. – ssaaradd Nov 21 '22 at 13:47
  • @ssaaradd a lambda is basically an anonymous function. A function without any name. The second example doesn't need the keyword `lambda`. I added an alternative version of the first example without lambda – aloisdg Nov 21 '22 at 14:21