You didn’t report the data you used to test, but the problem probably occurs because the weight should be a number, but in the code you manipulate it as a string (since input
returns a string).
The problem with comparing strings is that even if they only have digits, they are compared lexicographically. That means the string '2'
is considered "larger" than the string '10'
:
print('2' > '10') # imprime "True"
This is the relevant part of documentation that explains this behavior:
Lexicographical Ordering for strings uses the Unicode code point number to order individual characters
That is, the lexicographical order takes into account the Unicode code points of each character (to better understand what a code point, suggest we start around here). But basically, each character has an associated numeric code (think of Unicode as an extension of ascii table - and make it clear that this is a simplification well coarse), and when comparing strings, the value of that code (which is the code point) is used to determine what is "higher" or "lower".
In the case, the code point of character '2'
is greater than the character of '1'
, so the string '2'
is considered "larger" than the string '10'
. Works the same way as a comparison between strings 'b'
and 'ac'
. Like the b
is "bigger" than the a
(the code point of character b
is greater than the character of a
), then lexicographically 'b' > 'ac'
- that is, in a string ordering, the 'b'
would come after 'ac'
, as well as the '2'
would come after '10'
:
lista = [ '2', '10' ]
print(sorted(lista)) # ['10', '2']
lista = [ 'b', 'ac' ]
print(sorted(lista)) # ['ac', 'b']
See here this code running
Finally, when comparing weights in this way, such as strings, the situation you described may occur: a weight with a smaller numerical value (for example, 2
) is considered larger than other (such as the 10
) because the data is as strings, and not as numbers.
If you want to take into account the numeric values (and not the code points of the string characters) to make the comparisons (and I believe this is what you want, since we are talking about weights), you must convert the weight to number, using int()
(if it can only have integers) or float()
(if you can have decimal places). You can also capture the ValueError
, which occurs if you do not enter a number, and ask it to type again. It would look like this:
while True:
try:
peso = int(input('Digite o peso: '))
break
except ValueError:
print('Peso deve ser um número')
Including, in the documentation has an example just like this.
That is, until a number is typed, keep asking you to type again. Thus you ensure that the weight will be a number and that comparisons are made correctly, taking into account the numerical value.
Another detail is that you may not need to store everything in a list, if the goal is only to get the highest and lowest value. One option would be to keep a register counter and update the highest and lowest values directly, without having to store in a list:
cont = 0
while True:
nome = input('Digite o nome: ')
while True:
try:
peso = int(input('Digite o peso: '))
break
except ValueError:
print('Peso deve ser um número')
if cont == 0:
maior_peso = menor_peso = peso
nome_maior = nome_menor = nome
else:
if peso > maior_peso:
maior_peso = peso
nome_maior = nome
elif peso < menor_peso:
menor_peso = peso
nome_menor = nome
cont += 1
resp = ' '
while resp not in 'SN':
resp = input('Você quer continuar? [S/N] ').strip().upper()[0]
if resp == 'N':
break
print(f'Ao todo você cadastrou {cont} pessoas.')
print(f'O maior peso cadastrado foi {maior_peso} de: {nome_maior}')
print(f'O menor peso cadastrado foi {menor_peso} de: {nome_menor}')
OBS: The difference to your code is that it only prints one of the names in the event of a tie. Already the loop You print all the names if you have more than one person with the minimum or maximum weight. In this case, I even understand why I have to keep everything on a list.
If you want to save the entries in a list, you don’t need two lists like you did (and insert them in a list and then remove them, it’s a complication for no reason). Simply add the register inside the loop, thus:
cadastros = [] # Obs: usar [] e list() dá no mesmo, ambos criam uma lista vazia
while True:
nome = input('Digite o nome: ')
while True:
try:
peso = int(input('Digite o peso: '))
break
except ValueError:
print('Peso deve ser um número')
if len(cadastros) == 0:
maior_peso = menor_peso = peso
else:
if peso > maior_peso:
maior_peso = peso
elif peso < menor_peso:
menor_peso = peso
cadastros.append((nome, peso))
resp = ' '
while resp not in 'SN':
resp = input('Você quer continuar? [S/N] ').strip().upper()[0]
if resp == 'N':
break
print(f'Ao todo você cadastrou {len(cadastros)} pessoas.')
print(f'O maior peso cadastrado foi {maior_peso} de: ', end='')
for (nome, peso) in cadastros:
if peso == maior_peso:
print(f'{nome}', end=' ')
print(f'O menor peso cadastrado foi {menor_peso} de: ', end='')
for (nome, peso) in cadastros:
if peso == menor_peso:
print(f'{nome}', end=' ')
Although the final part is somewhat repetitive, it would simplify creating a function:
def encontrar_nomes_por_peso(cadastros, peso_busca, descricao):
print(f'O {descricao} peso cadastrado foi {peso_busca} de: ', end='')
for (nome, peso) in cadastros:
if peso == peso_busca:
print(f'{nome}', end=' ')
print()
encontrar_nomes_por_peso(cadastros, maior_peso, 'maior')
encontrar_nomes_por_peso(cadastros, menor_peso, 'menor')