Python Queue Code - How to check if there is an element with a specific name in the queue and its index position?

Asked

Viewed 1,053 times

3

I’m making a queue code from a bank where you need to type the name, age, weight and gender class Person and class Queue and this code has some options that must be entered according to the user’s will. (Apparently the code works)

I wanted to know how to get this code in line allows for a check if a specific name of the element is in the queue and displays the index of where the name is?

the code line is in elif opcao == 6:

# Código de fila
class Fila:
    inicio = None
    fim = None

class Pessoa:
    nome: str
    idade: int
    peso: float
    genero: str
    proximo = None

def inserir_elemento(fila, pessoa):
    if fila_vazia(fila):
        fila.inicio = pessoa
        fila.fim = pessoa
    else:
        fila.fim.proximo = pessoa
        fila.fim = pessoa
    print(f"Elemento {pessoa.nome} foi inserido\n")

def excluir_elemento(fila):
    if fila_vazia(fila) == True:
        print("A fila está vazia")
    else:
        elemento_excluido = fila.inicio
        proximo_fila = fila.inicio.proximo
        del fila.inicio
        fila.inicio = proximo_fila
        if fila.inicio == None:
            fila.fim = None
        print(f"O elemento ({elemento_excluido.nome}) foi excluído\n")

def fila_vazia(fila):
    verificar_fila = (fila.inicio == None and fila.fim == None)
    return verificar_fila

def tamanho_fila(fila):
    if (fila_vazia(fila) == True):
        return 0
    else:
        contador_fila = 0
        ver_pessoa = fila.inicio
        while ver_pessoa != None:
            contador_fila += 1
            ver_pessoa = ver_pessoa.proximo
        return contador_fila

def imprimir_elemento(fila):
    if fila_vazia(fila):
        print("A fila está vazia\n")
    else:
        ver_pessoa = fila.inicio
        while ver_pessoa != None:
            print(ver_pessoa.nome, ver_pessoa.idade, ver_pessoa.peso, 
            ver_pessoa.genero, end=" " if ver_pessoa.proximo != None else print())
            ver_pessoa = ver_pessoa.proximo

fila_encadeada = Fila()
opcao = 1
while opcao != 6:
    print ("1 - Inserir")
    print ("2 - Excluir")
    print ("3 - Imprimir")
    print ("4 - Informar tamanho da fila")
    print ("5 - Informar se a fila está vazia")
    print ("6 - Sair")
    opcao = int(input("Informe a opção: "))
    if opcao == 1:
        nome_informado = str(input("Informe o nome da pessoa: "))
        idade_informada = int(input("Informe a idade de {}: ".format(nome_informado)))
        peso_informado = float(input("Informe o peso de {}: ".format(nome_informado)))
        genero_informado = str(input("Informe o gênero de {}: ".format(nome_informado)))
        novo_elemento = Pessoa()
        novo_elemento.nome = nome_informado
        novo_elemento.idade = idade_informada
        novo_elemento.peso = peso_informado
        novo_elemento.genero = genero_informado
        inserir_elemento(fila_encadeada, novo_elemento)
    elif opcao == 2:
        excluir_elemento(fila_encadeada)
    elif opcao == 3:
        imprimir_elemento(fila_encadeada)
    elif opcao == 4:
        print(f"Tamanho da Fila: {tamanho_fila(fila_encadeada)}\n")
    elif opcao == 5:
        if(fila_vazia(fila_encadeada) == True):
            print(f"A fila está vazia\n")
        else:
            print(f"A fila não está vazia e possui {tamanho_fila(fila_encadeada)} elemento(s)\n")
    elif opcao == 6:
        print("Saindo...\n")
    else:
        print("Opção inválida, digite uma opção válida no menu\n")
  • 2

    By the convention on the name of Fila and Pessoas, They are classes. And by mistake you didn’t define them. Are you sure you’re not skipping steps to learn Python? If you want to learn step by step, calmly, recommend the videos from Gustavo Guanabara, from the Video Course.

  • It seems to me that you are learning very randomly and are missing some interesting concepts. As for example, how to identify error messages. Or in Portuguese at Wiki (section 8.3)

  • Where are the files containing the Queue() and People code() ?

  • I don’t know what you’re talking about

  • 2

    python does not come with any class or function called Fila() or Pessoas(), so an error is thrown, because python cannot identify what these classes are. If you created these classes you need to import them into your code so you can use them. Search about import and after you understand, add the Imports to your code. It would look something like from meu_modulo import Fila, Pessoas

4 answers

8

I believe that it is not importing the class Fila() module.

Ex: from <modulo onde está a classe> import Fila

Your mistake looks like this, and it’s correct because I didn’t declare the class module Fila

>>> filaencadeada = Fila()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Fila' is not defined
>>> 
  • It is true, you must import your class so that it is seen by this module. Another thing you should look at is option validations, remembering that inputs always return str is you are compared as int, convert user inputs to inside or make comparisons as string.

  • I guess I still don’t get it

8

Given the implementation, I would say that a list would already solve your problem well enough, not needing to implement a chained list for it, but considering that the chained list is part of the problem and should be implemented I recommend that you separate the responsibilities.

The attribute proximo belongs to the node of a chained list, not of the person, so much so that it makes no sense for a person to have value in proximo if it is not in a queue. The instance of Pessoa will only be the value stored in the queue node, it should not be the node itself.

Using the dataclasses introduced in Python 3.6, you can implement the class Pessoa as follows:

from dataclasses import dataclass

@dataclass
class Pessoa:
    nome: str
    idade: int
    peso: float
    genero: str

Note that when using the dataclasses, you just need to annotate the field types of your class, different from what you did that was set class attributes; if you are not working with dataclasses, I recommend that you read how to work with instance attributes and what are her differences to the class.

To implement the chained list, you will need two classes: the node, which will represent each item in the list, and the list by itself. The node will only need two fields: the stored value, which in this example will be a person, and a reference to the later node.

from typing import Any

@dataclass
class No:
    valor: Any
    proximo: 'No' = None

And for the list itself could do something like:

class Lista:
    def __init__(self):
        self.primeiro = None

    def inserir(self, no: No):
        if self.primeiro is None:
            self.primeiro = no
            return

        cursor = self.primeiro
        while cursor.proximo is not None:
            cursor = cursor.proximo
        cursor.proximo = no

    def __len__(self):
        if self.primeiro is None:
            return 0

        tamanho = 0
        cursor = self.primeiro
        while cursor.proximo is not None:
            cursor = cursor.proximo
            tamanho += 1
        return tamanho

Can complete with the methods you need.

  • Dude for now I’m not wearing any kind of import queue, so I don’t really understand what you did

  • @Alexf. What would be "import in queue"?

  • those imports of your code, would that not?

  • @Alexf. Python native module imports only

5

Formatting

Your code doesn’t fit the style suggested by PEP 8. Python programmers often use PEP 8 as a guide to formatting code. I strongly recommend that you refactor your code to meet these guidelines. For example, the function inserirElemento would become inserir_elemento.

Object orientation

Note that you have made a clear separation between data and behavior. When reading your code, note that the classes describe data, while the functions describe behaviors. This becomes even clearer if you notice that all of your functions require a class instance Fila.

There is nothing wrong with separating data and behavior. In fact, declarative paradigm languages generally favor this type of approach. However, in the case of Python, I recommend turning these functions into methods of your classes. (especially the class Fila).

Separation of responsibilities

When creating a computer program, code elements can usually be divided into categories. When reading your program, I identify three categories:

  1. Business: Elements responsible for representing the domain of the problem you are solving.
  2. Mechanism: Elements responsible for modifying and changing data in a generic and reusable way.
  3. Presentation: Elements responsible for communicating with the outside world.

Examples:

  • That while with a lot of ifs is an element of presentation.
  • The class Pessoa is a business element.
  • The class Fila is a mechanism.

You should organize your code so that the elements of each category do not mix, just relate and fit, as if they were little pieces of lego.

See this function here, for example:

def imprimirElemento(fila):
    if filaVazia(fila):
        print("A fila está vazia\n")
    else:
        verPessoa = fila.inicio
        while verPessoa != None:
            print(verPessoa.nome, verPessoa.idade, verPessoa.peso, 
            verPessoa.genero, end=" "if verPessoa.proxima != None else print())
            verPessoa = verPessoa.proxima

This function prints data on the screen (presentation), iterates through a queue (mechanism) and formats the person’s data (business).

If you change the queue implementation, this function will break. If you change the person’s implementation, this function will break. If you change the way the data is displayed, this function will break. That is, this function is a tangle of responsibilities. You must separate these responsibilities.

There are several books on this subject. If you want to go deeper, you can start by Object-Oriented Reengineering Patterns.

Examples of implementation

Let me give you two examples of implementation: Classes Fila and Pessoa.

Remember that the queue is a mechanism. You know beforehand that you will need to use a queue, and you know what operations that queue will have to perform. The queue should be generic and without any dependence on business classes. In other words, create this class bearing in mind that you should be able to reuse it in any program that needs a queue.

class Nodo():
    def __init__(self, valor):
        self.valor = valor
        self.proximo = None

class Fila():
    def __init__(self):
        self.primeiro = None
        self.ultimo = None
        self.contador = 0

    def enfileirar(self, valor):
        novo = Nodo(valor)

        if self:
            self.ultimo.proximo = novo
        else:
            self.primeiro = novo

        self.ultimo = novo
        self.contador += 1

    def desenfileirar(self):
        if not self:
            raise IndexError()

        primeiro = self.primeiro

        if primeiro == self.ultimo:
            self.ultimo = None
            self.primeiro = None
        else:
            self.primeiro = primeiro.proximo

        self.contador -= 1

        return primeiro.valor

    def __len__(self):
        return self.contador

    def __bool__(self):
        return len(self) > 0

    def __iter__(self):
        temp = self.primeiro

        while temp:
            yield temp.valor
            temp = temp.proximo

Note that all operations have been defined within the class Fila. She is totally self-aware.

The class Pessoa should be responsible not only for storing the data of the person, but also for containing all the expected behaviour of a person. In the case of the domain of your problem, I identify that the behaviors are:

  • Generate a textual representation of the person
  • Deciding whether two instances represent the same person in the real world

Note that it is not the responsibility of this class to print things on the terminal.

class Pessoa():
    def __init__(self, nome, idade, peso, genero):
        self.nome = nome
        self.idade = idade
        self.peso = peso
        self.genero = genero

    def __eq__(self, outro):
        if not isinstance(outro, type(self)):
            return False

        return (
            self.nome == outro.nome and
            self.idade == outro.idade and
            self.peso == outro.peso and
            self.genero == outro.genero
        )

    def __str__(self):
        return f'Nome: {self.nome}; Idade: {self.idade}; Peso: {self.peso}; Gênero: {self.genero}'

See that this form of implementation allows you to test each piece of code separately. This is very, very important in more complex systems, and you should already get the custom of creating easily testable codes.

Answering to your question

I was wondering how to get this queued code to allow for a check if a specific element name is in the queue

You can create a function for this.

def procurar_por_nome(fila, nome_procurado):
    for pessoa in fila:
        if pessoa.nome == nome_procurado:
            return pessoa

    return None

fila = Fila()

fila.enfileirar(Pessoa('Bianca', 24, 50, 'F'))
fila.enfileirar(Pessoa('Jéssica', 28, 54, 'F'))
fila.enfileirar(Pessoa('Maisa', 22, 44, 'F'))
fila.enfileirar(Pessoa('Tatiane', 34, 55, 'F'))

nome_procurado = input('Nome: ')

pessoa = procurar_por_nome(fila, nome_procurado)

if pessoa:
    print(pessoa)
else:
    print('Pessoa não encontrada')

(Note that I used the classes I suggested)

However, it would be much better if you created a search method in the class itself Fila that receives a predicate and returns the first element that meets the predicate.

class Fila():
    # ... outros métodos que já mostrei...

    def encontrar(self, predicado):
        for item in self:
            if predicado(item):
                return item

        return None

Now you can use this method to find a person under any criteria, not just by name.

nome_procurado = input('Nome: ')

pessoa = fila.encontrar(lambda pessoa: pessoa.nome == nome_procurado)

if pessoa:
    print(pessoa)
else:
    print('Pessoa não encontrada')

Observing

There are many improvements to be made to the code I suggested. My intention was not to show a perfect code, but to open your eyes to other ways to approach the problem.

  • A question about answering your question it is necessary to create a def for that reason?

  • @Alexf. I rewrote this part to make it clearer.

  • Didn’t work out..

4

When creating classes it is good practice to start with uppercase class Pessoa, any method of a class that is part of the instance (non-static methods) must have as its first parameter self, some of your methods are missing this, class properties should also have the self and must be within the method __init__, the class Pessoa be missing method __init__ put those attributes inside it, there are some errors like pessoa.fila = [] in this command you are accessing the property that class Pessoa has but in its implementation the class does not own this property, there is another also in this part print (fila.excluirElemento()) where you use the variable fila that wasn’t even set, take a look in that question on how to use the self

Class Pessoa(recommended implementation)

class Pessoa:
    def __init__(self, nome, idade, peso, genero):
        self.nome = nome
        self.idade = idade
        self.peso = peso
        self.genero = genero


davi = Pessoa("Davi", 27, 89, 1)
  • the class fila you’re right?

  • as I said in reply, you forgot to put the self in the methods and ta using an attribute of the Person class that does not exist that in the case is pessoa.fila its implementation of the Person class does not have the attribute fila

Browser other questions tagged

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