Avoid blank input data

Asked

Viewed 821 times

0

I have an empty list that will be fed by inputs.

In case, how do I go through the list and check if any data has been entered blank and treat it to fill in again?

Example:

lista = []

variavel_1 = lista.insert(0,input("Digite o numero: "))
variavel_2 = lista.insert(1,input("Digite o segundo numero: "))

Upshot: lista = ['1',' ']

I wanted to do it in a way that wasn’t treated by if's in the input or while. Could it be? Or is there a Python function that calls in input not to enter empty data?

  • That part here: "do in a way that is not treated by ifs in the input" means what? That the verification should be done only after the whole completed list?

  • I don’t know if it would be right.. But I didn’t want to deal with ifs in input.

  • Do the checks right in the lobby as @Filipemachado suggested.

  • All right! Thanks..

5 answers

4


Contrary to what some responses have stated, you should not remove items from the list within it loop that iterates on it. It may even work in some cases, but in others it won’t, as we can see below.

Consider the case below, which removes elements that are empty strings:

lista = [ '', '', '', 'x' ]
for x in lista:
    if x == '': # se for string vazia, remove
        lista.remove(x)

# deveria sobrar só o 'x', mas...    
print(lista) # ['', 'x']

This code prints out:

['', 'x']

One of the elements that should be removed was not.


Why does this happen?

To better understand what happened, let’s use another list:

lista = [ '1', '2', '3', 'x' ]
for x in lista:
    if x.isdigit(): # se for um dígito, remove
        lista.remove(x)

print(lista) # ['2', 'x']

Now I’m using isdigit() to remove strings that contain only digits. However, the result is the list ['2', 'x'].

This is because in the first iteration of for, it takes the first element from the list (the string '1'). Like isdigit() returns True for this string, it enters the if and the '1' is removed from the list.

In the second iteration of for, it takes the second element from the list. But as the '1' has already been removed, the second element is now the string '3' (that is, the string '2', that should have been removed, was skipped). That’s why the '2' still appears in the final result.

In more detail:

  • first iteration of for, the list goes like this:
[ '1', '2', '3', 'x' ]
  • the first item in the list is checked ('1'), and how isdigit() returns True, this is removed. IE, now the list is like this:
[ '2', '3', 'x' ]
  • in the second iteration of for, he takes the second element, which is the '3', and isdigit() also returns True, then this one is removed. Now the list is like this:
[ '2', 'x' ]
  • in the third iteration of for, he tries to catch the third element, but as the list only has 2 elements, the loop closes.

You can make sure that this happens by putting a print in the for:

lista = [ '1', '2', '3', 'x' ]
for x in lista:
    print('testando', x)
    if x.isdigit():
        print('removendo', x)
        lista.remove(x)

The exit is:

testando 1
removendo 1
testando 3
removendo 3

As you can see, the '2' was "jumped". And the 'x' not even checked (if it was also a string that contains only digits, that is, something that should be removed, it also would not be removed).


So how do I do?

If you want to delete some elements from the list by following certain criteria, you can create another list containing only the elements you need. Ex:

lista = [ '', '', '', 'x' ]
# manter apenas os elementos que não forem vazios
lista = [ x for x in lista if x != '' ]
print(lista) # ['x']

I used the syntax of comprehensilist on, to get the elements that are not empty strings. In this case, I assigned them to the same list, but you could create another one if you wanted:

lista = [ '', '', '', 'x' ]
# manter apenas os elementos que não forem vazios
outra_lista = [ x for x in lista if x != '' ]

Thus there is no problem cited at the beginning, of improperly skipping some elements.

Another alternative is to use the module itertools, and its function filterfalse:

from itertools import filterfalse

lista = [ '', '', '', 'x' ]

lista = list(filterfalse(lambda s: s == '', lista))
print(lista) # ['x']

filterfalse considers the elements for which the condition is false. In this case, I used as a condition a lambda that checks if the string is empty, then it will return the elements that are not empty.


About the other doubts:

how do I go through the list and check if any data has been entered blank and treat it to fill in again?

In this case you could do something like this:

lista = [ '', '', '', 'x' ]
for i, _ in enumerate(lista):
    while lista[i] == '':
        lista[i] = input('digite um número:')

The while serves to ask the user to type something, and while this something is the empty string, it asks you to type again. If the item is not empty, it does not enter the while and item is not modified.


I wanted to do it in a way that wasn’t treated by if's in the input or while. Could it be? Or is there a Python function that calls in input not to enter empty data?

Why don’t you want to use if or while? They’re two of the most basic programming structures, and it’s okay to use them.

In the case of input, just make a loop asking to enter the information, until it is what you want:

while True:
    s = input('digite o número: ')
    if s != '':
        break

If the string s is empty, it continues on while, asking you to type again. If it is not empty, enter if and the break interrupts the loop.

Although in your case you are asking you to enter a number, so why not just validate if it is an even number?

while True:
    try:
        n = int(input('digite o número: '))
        break
    except ValueError:
        print('Não foi digitado um número')

If no number is entered, int() will launch a ValueError and fall into the block except (which in turn informs that no number has been entered), and the while continues, asking the user to type again. If the conversion to number is correct, the code falls on break, interrupting the loop.

In the case, int() only accepts whole numbers. But if you want numbers with decimals, just switch to float().

So you guarantee right at the beginning that your list will only have valid values, and you don’t even need to treat them afterwards.

One more thing: if you want to add values at the end of the list, use append instead of insert. Just do lista.append(valor), that the value is inserted at the end of the list (see more details in documentation).
Another detail is that lista.insert returns None, then it makes no sense to assign the return of insert in a variable, as you did in variavel_1 and variavel_2.


On "blank data"

It is not very clear what you consider a "blank die". If it is only a space, then it is okay to use what one of the answers suggested (compare to ' ' - note that there is a space between the quotes). In my examples I used an empty string (''), which is what input returns when only one is typed ENTER. Both are valid, depending on what you need.

But what if multiple spaces are typed (e.g.: ' '), do you also consider it to be "blank data"? If so, a way to compare would be:

# s é a string que estou verificando se é "em branco"
if s.isspace() or s == '':
    # em branco (ou vazio)

I used the method isspace() that checks if the string only has spaces - remembering that the definition of "space" that it uses is "a character that has the Unicode category Zs ("Separator, space"), or the two-way class is WS, B or S." (see here the complete list of these characters).

But isspace() requires there to be at least one character in the string, so I also test if the string is empty. Another way to do this is to eliminate the spaces at the beginning and end of the string (using strip()) and check that what is left is empty:

if s.strip() == '':
    # s é "em branco"
  • 1

    Man, excellent your explanation! Thank you very much... I will follow this way.

2

It seems you forgot to close parentheses at the end of each variable assignment, but I guess that’s not what comes to the case.

Honestly, I don’t see many alternatives to scrolling through the list and removing items other than using one if.

If it helps, a simple solution can be:

lista = []

variavel_1 = lista.insert(0,input("Digite o numero: "))
variavel_2 = lista.insert(1,input("Digite o segundo numero: "))
for item in lista:
    if item == ' ':
        lista.remove(' ')

print(lista)
  • True! Corrected. If there is no other way, I will try anyway.

  • It worked out! Thanks..

  • @M4estri Just one detail: remove items from the list inside the for not always going to work, I put an example in my answer

1

Unused while or if, the best you can do for short is to force input typing. If you will only receive numbers, use int() or float() as a wrap of input() returns an error as below

variavel_1 = lista.insert(0,float(input("Digite o numero: ")))
variavel_2 = lista.insert(1,float(input("Digite o segundo numero: ")))

Digite o numero: 1
Digite o segundo numero: 

--//--

ValueError                                Traceback (most recent call last)
<ipython-input-6-13b4d3494daf> in <module>
      2 
      3 variavel_1 = lista.insert(0,int(input("Digite o numero: ")))
----> 4 variavel_2 = lista.insert(1,int(input("Digite o segundo numero: ")))

ValueError: invalid literal for int() with base 10: ''

If you do not want the error occurring, you can use the function try:

try:
    variavel_1 = lista.insert(0,float(input("Digite o numero: ")))
    variavel_2 = lista.insert(1,float(input("Digite o segundo numero: ")))
except Exception as e:
    #Insira a aqui a tua tratativa para o erro
    print("Insira um número válido!")

Digite o numero: 
Insira um número válido!

Otherwise, I’d have to wear a if in a loop for or while to verify.

0

Apart from the preconception against whiles... :-D

lista = []
x = 1
while x < 3:
    v = input(f"Digite o {x}º número: ")
    try:
        lista.append(float(v))
        x += 1
    except ValueError:
        print("Valor inválido, redigite.")

print(lista)

Which results in:

Digite o 1º número: 9
Digite o 2º número: r
Valor inválido, redigite.
Digite o 2º número:
Valor inválido, redigite.
Digite o 2º número: 2
[9.0, 2.0]

Imagining that you already have the list, but want to do a validation and complete if necessary:

def float_ou_nada(x):
    try:
        return float(x)
    except ValueError:
        return None

# Lista inicial, assumindo que esta já tenha sido lida anteiormente
lista = [1, "x", ""]
# Limpa a lista
lista = [v for v in lista if float_ou_nada(v) is not None]
# Testa se a lista tem o tamanho desejado, pegunda os elementos que faltam
while len(lista) < 2:
    v = input(f"Digite o {len(lista)+1}º número: ")
    try:
        lista.append(float(v))
    except ValueError:
        print("Valor inválido, redigite.")
print(lista)

which results in:

Digite o 2º número: o
Valor inválido, redigite.
Digite o 2º número:
Valor inválido, redigite.
Digite o 2º número: 9
[1, 9.0]

You can also swap float for int if you want integers.

0

If you want to restrict a particular entry you need to create a condition. One way to solve this problem is by using try and except.

The idea would be: the program will try to do an action and if it n succeeds it will go the other way.

Example:

lista = []

[lista.append(input('Digite o {}º número: ' .format(x+1))) for x in range (3)]

for x in lista:
    try: float(x)
    except: lista.remove(x)


# Outra forma:
# for x in lista:
#     try: 
#         float(x)
#     except: 
#         lista.remove(x)

So whatever’s on the try he will try to do, if at any time there is error in the code he will go to the except doing some other action (such as some error message)

  • Gui Reis. Avoid putting lengths, signature and lexical abbreviation.

Browser other questions tagged

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