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']
See here an alternative way to solve your problem.
– Solkarped