How to sort a list through an object attribute?

Asked

Viewed 57 times

-2

I am doing an activity, and wanted to make the list come out alphabetically from the name of the project, someone would have some solution ?

class Projeto:

    def __init__(self, nomep, contato):  
        self.nomep = nomep
        self.contato = contato

    def mudar_contato(self, contato_antigo, contato_novo):
        if self.contato == contato_antigo:
            self.contato = contato_novo
            return True 
        else:
            return False  

class Interface:

    projeto = []

    def cadastrar_projeto(self):
        nomep = input('Quais é o nome do projeto?\n')
        contato = input('Quais é a contato desejada?\n')

        self.projeto.append(Projeto(nomep, contato))
        print('Projeto adicionado!')

    def listar_projetos(self):
        for i, projeto in enumerate(self.projeto):
          print(i, projeto.nomep, projeto.contato)

    def mudar_contato(self):
        numero_projeto = input('Qual é o número de listagem do projeto?')
        numero_projeto = int(numero_projeto)

        contato_antigo = input('Qual é o contato atual?\n')
        contato_novo = input('Qual é o contato desejada?\n')
        sucesso = self.projeto[numero_projeto].mudar_contato(contato_antigo, contato_novo)

        if sucesso:
            print('Alteração realizada!')
        else:
            print('Erro ao tentar alterar contato!')
    
    def excluir_projeto(self):
        numero_projeto = input('Qual é o número de listagem do projeto?')
        numero_projeto = int(numero_projeto)
        self.projeto.pop(numero_projeto)

    def loop(self):
        while True:
            cmd = input('\n1 - Listar projeto\n2 - Cadastrar projeto\n3 - Mudar contato\n4 - Excluir Projeto\n')
            if cmd == '1':
                self.listar_projetos()
            elif cmd == '2':
                self.cadastrar_projeto()
            elif cmd == '3':
                self.mudar_contato()
            elif cmd == '4':
                self.excluir_projeto()
            else:
                print('Opção inexistente')
                continue


if __name__ == '__main__':
    interface = Interface()
    interface.loop()

1 answer

0

Use the function sorted and enter a value for the argument key. This value will explain to the function sorted the logic to be applied when sorting the elements.

One widely used way is to use an anonymous function (lambda) for this. Ex:

def listar_projetos(self):
    for i, projeto in enumerate(sorted(self.projeto, key=lambda p: p.nomep.lower())):
      print(i, projeto.nomep, projeto.contato)

The way I wrote it, the job sorted will sort the projects in the list self.projeto looking only at the attribute nomep of each of them.

Note that I used the method lower() to order (I assumed that nomep is a string). This causes lower or upper case letters to have no effect on sorting.

Edit: a simple example of method to delete a project from the list (as discussed in the comments).

def excluir_projeto_por_nome(self, nome):
    projetos_para_remover = []
    for projeto in self.projeto:
        if projeto.nomep == nome:
            projetos_para_remover.append(projeto)
    self.projeto = [p for p in self.projeto if p not in projetos_para_remover]
         
  • In fact it worked, but the function of excluding by the index is using the initial value, before the ordering, would have some way to update the values of the index according to the ordering, or some other suggestion ?

  • I suggest one of two approaches: keeping the project number as an attribute of the project itself, making it independent of its position on the list (e.g., adding the attribute self.nump at the __init__ class Projeto), or keep the list projeto of your class Interface always ordered - that is, in the method cadastrar_projeto, instead of using the method append from the list, find out in which position of the list the project should be inserted to keep it orderly and use the method insert of lists.

  • How do I get the Insert to find out in which position it needs to be inserted to keep it orderly ?

  • This is an entirely different problem, take a look at other questions like https://answall.com/questions/446761/inser-elements-na-posi%C3%A7%C3%A3o-correct-in-a-list-ordered for example.

  • Is there any simpler way in which I just type the name and it select the same and delete ?

  • You can create a method excluir_projeto_por_nome for this - given a name as argument, the method iterates over the list of projects, finds the project(s) whose name is equal to the name given as argument, and finally removes them from the list.

  • Could you exemplify ? I’m not from the area of computing, but my course requires this subject and I’m having a lot of difficulty.

  • I edited my answer to include an example of how to do this, I hope it’s clear.

  • It returned me this error there in the loop: Typeerror: excluir_project_por_name() Missing 1 required positional argument: 'name'

  • Did you pass the project name to delete? Ex: self.excluir_projeto(nome='meuprojeto01').

  • It is necessary an input for it to read the name of the project to be deleted. In this case, I would have to put a name = input("") in the method ?

  • Could be, in which case you would need to remove the argument nome the definition of the method: def excluir_projeto_por_nome(self):. Or else put the input into your method loop. At your discretion.

  • And in case the contact change, since the index is no longer necessary, have any idea how it would look ?

Show 8 more comments

Browser other questions tagged

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