Sort two lists simultaneously, by notes in ascending order, then by name

Asked

Viewed 100 times

4

I have created two lists, one of notes and one of names. The program must sort notes in ascending order, but it must sort names as well. I tested it as follows:

notas = [5, 7, 9, 3] 
nomes = ["Alfredo", "Camila", "Debora", "Joao"]

Fortunately it worked, with the following result:

[9, 7, 5, 4]
["Debora", "Camila", "Alfredo", "Joao"]

I tested it again:

notas = [5, 9, 2, 7] 
nomes = ["Joao", "Debora", "Camila", "Alfredo"]

It went wrong in the result:

[9, 7, 5, 2]
['Camila', 'Joao', 'Alfredo', 'Debora']

I tried many times and could not solve.

My code:

#---------------------------------------------------------------
lista_notas = []
backup_notas = []
ordem_list = []
lista_nomes = []
backup_nomes = []
i_to_while = 0
ii_to_while = 0
#---------------------------------------------------------------
def decrescente(notas):
    lista_notas.append(notas)
    backup_notas.append(notas)
    lista_notas.sort()
    lista_notas.reverse()
    return lista_notas, backup_notas
#---------------------------------------------------------------
def descobrindo_posicoes(notas, original):
    ii = 0
    while ii != len(notas):
        ordem = notas.index(original[ii])
        ordem_list.append(ordem)
        ii+=1
    return ordem_list
#---------------------------------------------------------------
def insere_nomes(nomes):
    lista_nomes.append(nomes)
    backup_nomes.append(nomes)
    return lista_nomes, backup_nomes
#---------------------------------------------------------------
def sincronizando_nomes(notas, ordem, nomes, original, original_notas):
    print(notas, ordem, nomes, original, original_notas)
    n = 0
    while n <= len(nomes)-1:
        nomes[n]= original[ordem[n]]
        nomes_resultado = nomes
        n+=1
    print("Antes de programa")
    print(original_notas)
    print(original)
    print("")
    print("Resultado")
    print(notas)
    print(nomes)
#---------------------------------------------------------------
while True:
    if i_to_while == 4:
        break
    decrescente(int(input("Suas notas? (4 notas suportadas): ")))
    i_to_while += 1
#---------------------------------------------------------------
descobrindo_posicoes(lista_notas, backup_notas)
#---------------------------------------------------------------
while True:
    if ii_to_while == 4:
        break
    insere_nomes(str(input("Seus nomes? (4 nomes suportados: ")))
    ii_to_while += 1
#---------------------------------------------------------------
sincronizando_nomes(lista_notas, ordem_list, lista_nomes, backup_nomes, backup_notas)
#---------------------------------------------------------------

2 answers

6

Further pythonic, could be:

Creating variables

notas = [5, 7, 9, 3]
nomes = ["Alfredo", "Camila", "Debora", "Joao"]

Gathering lists

l = list(zip(nomes, notas))

print(l)
[('Alfredo', 5), ('Camila', 7), ('Debora', 9), ('Joao', 3)]

Ordering by note

l.sort(key=lambda x: x[1])

print(l)
[('Joao', 3), ('Alfredo', 5), ('Camila', 7), ('Debora', 9)]

Separating the lists

nomes, notas = zip(*l)

print(nomes)
('Joao', 'Alfredo', 'Camila', 'Debora')

print(notas)
(3, 5, 7, 9)

5


If the idea is to synchronize the two lists (i.e., sort the notes, and then maintain the order of their names), you don’t need all this complication.

Instead of having two lists, I suggest having only one, storing tuples that contain the name and the respective note (but also have an alternative with two lists at the end).

So it would look like this:

nomes_notas = []
quantidade = 4
for _ in range(quantidade):
    nome = input('digite o nome:')
    nota = int(input('digite a nota:'))

    # insere uma tupla contendo o nome e a nota
    nomes_notas.append((nome, nota))

# ordena pela nota em ordem decrescente
nomes_notas.sort(key=lambda t: t[1], reverse=True)
print(nomes_notas)

I mean, I read the name and the note, and then I insert a tuple - the (nome, nota): Note the parentheses, they are not redundant. If I did nomes_notas.append(nome, nota), I would be passing two parameters to append and it would be a mistake. By placing this extra pair of parentheses, I am creating a tuple containing the name and note, and this tuple is inserted into the list.

Then, just sort using the note value (is what the key=lambda... makes, takes the second element of the tuple - the one in the position 1, since the first position is zero), and the reverse=True makes it in descending order.

In the end the exit will be something like:

[('ciclano', 5), ('trajano', 4), ('beltrano', 3), ('fulano', 1)]

But if you want to create separate lists for names and notes, just do:

nomes = [ t[0] for t in nomes_notas ]
notas = [ t[1] for t in nomes_notas ]

But if you want, you can keep the data in two lists - which I don’t suggest, because if each name is tied to a note, then it makes more sense to group this information together, rather than keep it separate and try to create a whole complicated scheme to synchronize it. But anyway, it would be something like this:

quantidade = 4
nomes = []
notas = []
for _ in range(quantidade):
    nomes.append(input('digite o nome:'))
    notas.append(int(input('digite a nota:')))

indices = sorted(range(len(notas)), key=lambda i: notas[i], reverse=True)
notas_ordenadas = [ notas[i] for i in indices ]
nomes_ordenados = [ nomes[i] for i in indices ]

That is, I create a list of indexes (the numbers from zero to the size of the list notas), and I sort these indices using as a basis the value of this index in the list of notes (is what the key there makes, for each index, picks the respective grade).

Then, just take the values of the names and notes in the order determined by the index list.

I reinforce again that this is a more confusing option, because if the notes and the names should be synchronized (each name has its note), I prefer to group this data and keep them together, as done in the first solution above.

Browser other questions tagged

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