Remove lowercase letters from a list

Asked

Viewed 230 times

3

I was trying to make a program that could identify whether a letter is in upper case or in Lower case in a list, so that it would delete the lower case letters.

frase = ("A B C D e f g h")
new = list ((frase).split())

for i in new :
    if i == i.lower() :
        new.remove(i)
    
print (new)

The problem is that this code returns ['A', 'B', 'C', 'D', 'f', 'h'] and not ['A', 'B', 'C', 'D'] as planned. I would like to know why this and how to fix.

  • See here an alternative way to solve your problem.

3 answers

3

You cannot remove elements from a collection with a for because it invalidates the iterator. Or you have to do it manually, which is risky if you don’t know how to do it right or you should create a new list with the items that should remain on the list:

frase = "A B C D e f g h".split()
novo = []
for i in frase:
    if i.isupper():
        novo.append(i)
print(novo)

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

3


As explained here and here, remove items from a list while iterating on it can bring unexpected results.

Modifying your code a little, we can understand what happens:

frase = ("A B C D e f g h")
new = list((frase).split())

for index, i in enumerate(new):
    print(new)
    print('verificando', index, i)
    if i == i.lower():
        print('removendo', i)
        new.remove(i)

The exit is:

['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h']
verificando 0 A
['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h']
verificando 1 B
['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h']
verificando 2 C
['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h']
verificando 3 D
['A', 'B', 'C', 'D', 'e', 'f', 'g', 'h']
verificando 4 e
removendo e
['A', 'B', 'C', 'D', 'f', 'g', 'h']
verificando 5 g
removendo g

That is, when arriving at index 4 (whose element is 'e'), this is removed, and the list becomes ['A', 'B', 'C', 'D', 'f', 'g', 'h'].

In the next iteration, you take the element at index 5, which is "g". Note that the "f" has been skipped as the "e" has been removed, the "f" is at index 4.

And after the "g" is removed, the list becomes ['A', 'B', 'C', 'D', 'f', 'h']. The next iteration would be index 6, but now the list no longer has this index and the loop closes.


To solve this, you don’t need to create the list new with all letters, only to then remove some. Just create an empty list and just add the elements you want. Also, if you just want to keep the letters uppercase, use isupper to check if it is capitalized:

frase = "A B C D e f g h"
new = []
for i in frase.split():
    if i.isupper():
        new.append(i)

Or use a comprehensilist on, much more succinct and pythonic:

frase = "A B C D e f g h"
new = [ i for i in frase.split() if i.isupper() ]

Just one detail: the question says you want to "delete the lower case letters". That is, numbers and punctuation marks, among other characters that are not letters, should be maintained? After all, if I only delete the lower case letters, the numbers and other characters should remain.

In this case, you could change the condition to if not i.islower() (is not lowercase). See how it makes a difference:

frase = "A B C D e f g h 1 2 3 ! @"

# remove as minúsculas (números e outros caracteres se mantém)
new = [ i for i in frase.split() if not i.islower() ]
print(new) # ['A', 'B', 'C', 'D', '1', '2', '3', '!', '@']

# só mantém as letras maiúsculas (qualquer outra coisa não é considerada)
new = [ i for i in frase.split() if i.isupper() ]
print(new) # ['A', 'B', 'C', 'D']

Of course, if the sentence has only letters, then it makes use of another, except for if you have letters of some alphabets that are not uppercase or lowercase. In Japanese, for example, there is no such concept, so the letters are neither uppercase nor lowercase (either isupper() how much islower() return False). And there are also the letters that are title case, like the Dž (LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON) (who are also not upper nor Lower case):

for s in ['親', 'Dž']:
    print(s.isupper(), s.islower()) # False False para ambos

Therefore, these letters will also make a difference, depending on the method chosen:

# contém letras de outros alfabetos que não são maiúsculas nem minúsculas
frase = "A B C D e f 親 Dž"

# remove as minúsculas
new = [ i for i in frase.split() if not i.islower() ]
print(new) # ['A', 'B', 'C', 'D', '親', 'Dž']

# só mantém as letras maiúsculas (qualquer outra coisa não é considerada)
new = [ i for i in frase.split() if i.isupper() ]
print(new) # ['A', 'B', 'C', 'D']
  • Thank you, but just out of curiosity, this Japanese letter has some meaning ?

  • @Smaug I actually picked up any character randomly, no special meaning...

  • I may be saying nonsense, because I don’t read Anji , but the character is oya(hi-á) means father and is also radical for kinship relations on the part of father.

  • 1

    @Augustovasques I went to search and it seems that the meaning is that same (But like I said, I did a random search for Japanese text and I took the first sentence that came up, it wasn’t an attempt to leave an "Easter Egg" or anything like that). It’s been a long time since I studied Japanese (and I forgot almost everything), but I remember that each Korean has several different pronunciations, depending on the context (in this case, "oyá" is one of them, but has many others - "Shin", "shita", "mizuka", etc)

1

I hope you help, I could improve but to resolve this issue.

def list(phrase):

new =[]

for i in frase :
    if i !=i.lower() :
        print('adicionando:{}'.format(i))
        new.append(i)
    
    
    
print (new)

if name == "main":

  frase = ("A B C D e f g h")
  lista(frase)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.