• Python

2022.1 Prova 4 - Questão 2: Nutrientes alimentares#

Neste exercício, vamos implementar um sistema que tem como objetivo auxiliar pessoas na sua dieta alimentar.

Para o desenvolvimento deste sistema, vamos utilizar dados de um projeto chamado TACO API que tem como objetivo mapear a composição alimentar de alimentos tipicamente brasileiros. Mais especificamente, vamos utilizar dois arquivos JSON: categoryList.json e foodList.json. O arquivo foodList.json que temos é apenas um sub-conjunto do arquivo original.

O arquivo categoryList.json possui uma lista de categorias alimentares. Ao todo são 15 e cada categoria possui um id e uma descrição, como apresentado abaixo:

[
  { "id": 1, "category": "Cereais e derivados" },
  { "id": 2, "category": "Verduras, hortaliças e derivados" },
  { "id": 3, "category": "Frutas e derivados" },
  ...
]

O arquivo foodList.json possui uma lista de alimentos e para cada alimento alguns atributos. Segue um exemplo abaixo:

{
    "id": 1,
    "description": "Arroz, integral, cozido",
    "base_qty": 100,
    "base_unit": "g",
    "category_id": 1,
    "attributes": {
      "humidity": {
        "qty": 70.1386666666667,
        "unit": "percents"
      },
      "protein": {
        "qty": 2.58825,
        "unit": "g"
      },
      "lipid": {
        "qty": 1.00033333333333,
        "unit": "g"
      },
      "cholesterol": {
        "qty": "NA",
        "unit": "mg"
      },
      "calcium": {
        "qty": 5.204,
        "unit": "mg"
      },

      ...
}

Cada alimento possui um id, uma descrição, uma quantidade base, a unidade de medida utilizada para esta quantidade base, a categoria que este alimento pertence e atributos, tais como, proteínas, colesterol, cálcio, entre outros.

Neste exercício estamos interessados em alguns macro-nutrientes e micro-nutrientes. Os macro-nutrientes que estamos interessados são: proteínas (protein) e carboidratos (carbohydrate). Os micro-nutrientes que estamos interessados são: zinco (zinc), ferro (iron) e cálcio (calcium).

Importante

Faça o download do exercício pelo link no final desta página!

Nível básico#

Todas as funções que vamos implementar deverão ser implementadas no arquivo funcoes.py. Este arquivo já vem com duas funções:

  • le_alimentos(): esta função lê os dados do arquivo foodList.json e retorna uma lista de dicionários com todos os alimentos.

  • le_categorias(): esta função lê os dados do arquivo categoryList.json e retorna uma lista de dicionários com todas as categorias.

Dica 1

Deixe os arquivos categoryList.json e foodList.json abertos em abas do VS Code para fazer estas questões. Eles tem uma estrutura complicada e é uma boa sempre tê-los como referência.

A primeira atividade neste exercício será implementar as seguintes funções no arquivo funcoes.py:

  • carrega_alimento(id): esta função recebe o id do alimento e retorna o dicionário do alimento. Se for fornecido um id que não existe então esta função precisa retornar {}.

  • carrega_categoria(id): esta função recebe o id da categoria e retorna o dicionário da mesma. Se for fornecido um id que não existe então esta função precisa retornar {}.

Atenção

Ao implementar os itens acima, utiliza as funções le_alimentos() e le_categorias() para carregar o dados de alimentos e de categorias.

A segunda atividade neste exercício será implementar as seguintes funções no arquivo funcoes.py:

  • macro_nutrientes(alimento_id): dado o id de um alimento, esta função precisa retornar um dicionário com a quantidade de proteínas (protein) e carboidratos (carbohydrate) que este alimento possui. O dicionário deve possuir o seguinte formato:
{"proteina": X, "carboidrato": Y}

Todas as quantidades representadas neste dicionário precisam ser em miligramas. Detalhe importante: alguns nutrientes tem as suas medidas em gramas ('g') e outros em miligramas ('mg'). Importante lembrar que 1g = 1000mg.

Existem alimentos que não tem proteínas ou carboidratos. Neste caso, estes valores não estarão presentes no arquivo json. Você precisa tratar isto e retornar o valor 0 nestes casos.


  • micro_nutrientes(alimento_id): dado o id de um alimento, esta função precisa retornar um dicionário com a quantidade de zinco (zinc), ferro (iron) e cálcio (calcium) que este alimento possui. O dicionário deve possuir o seguinte formato:
{"zinco": X, "ferro": Y, "calcio": Z}

As mesmas regras utilizadas em macro_nutrientes devem ser aplicadas aqui.

Proficiente#

Será que existem alimentos que possuem "traços" de algum nutriente?

A quantidade de alguns nutrientes em alguns alimentos é tão pequena que muitas vezes é difícil medir, mas não pode ser ignorada. Por isso, que em muitos casos temos o valor do nutriente como sendo igual "Tr".

Implemente uma função chamada lista_Tr(nutriente) que lista os ids de todos os alimentos que possuem traços de um certo nutriente. Isso é indicado na lista com o valor do nutriente sendo igual a "Tr".

Qual a soma de micro e macro nutrientes?

Implemente uma função chamada soma_nutrientes(alimento_id, tipo_nutriente) que, dado o id de um alimento e o tipo de nutriente que queremos analisar (micro ou macro), retorna o nome do alimento (description) e a soma dos nutrientes micro ou macro. Um exemplo de utilização é:

>> print(soma_nutrientes(130, 'micro'))
{'alimento': 'Mandioca, crua', 'micro': 15.663333333333332}

>> print(soma_nutrientes(130, 'macro'))
{'alimento': 'Mandioca, crua', 'micro': 37300.00000000001}

Se for informado um id de alimento que não existe então a função soma_nutrientes deve retornar: {'alimento': '', 'macro': 0} ou {'alimento': '', 'micro': 0} dependendo do parâmetro tipo_nutriente que foi informado.

E caso alguém defina um valor errado para o parâmetro tipo_nutriente então a função deve retornar a seguinte mensagem:

Você escolheu um tipo de nutriente não válido.

  • Quantos alimentos existem em cada categoria?

Implemente uma função chamada alimentos_por_categoria() que retorna uma lista de dicionários com a seguinte estrutura:

[
    {'categoria': 'Nome da categoria', 'quantidade': N},
    {'categoria': 'Nome da categoria', 'quantidade': N},
    ...
]

Listando todas as categorias existentes em categoryList.json com a sua respectiva quantidade de alimentos existentes em foodList.json. Lembre-se que o arquivo JSON que temos é um subset do original. Observação: o nome da categoria está armazenado na chave category.

Avançado#

  • Quais são os alimentos mais ricos em proteína por categoria?

Implemente uma função chamada alimentos_mais_ricos_em_proteina que considera todas as categorias e para todos as categorias encontra aquele alimento mais rico em proteina. Esta função deve retornar um dicionário com a seguinte estrutura:

[
    {'categoria': 'Nome da categoria', 'alimento': 'Nome do alimento', 'proteinas': N},
    {'categoria': 'Nome da categoria', 'alimento': 'Nome do alimento', 'proteinas': N},
    ...
]

O valor das proteinas, ou seja, o valor de N precisa ser em miligramas.

Para alguns alimentos são encontrados valores que não são numéricos no campo relacionado com a quantidade de proteína. Os valores encontrados são 'NA' e 'Tr'. Para estes casos deve-se considerar o valor 0.

Algumas categorias não tem alimentos. Neste caso o valor para alimento deve ser '' e o valor para proteinas deve ser 0.

Segundo tópico do Avançado#

Para determinadas dietas muitas vezes é necessário criar um cardápio rico em proteínas e fraco em carboidratos. Pensando nisto, implemente uma função chamada filtrar_alimentos que recebe três parâmetros:

  • categoria: este parâmetro deve receber o id da categoria do alimento;
  • carboidrato: este parâmetro deve receber um dicionário com a seguinte estrutura:
{'relacao': 'maior', 'valor': N}

onde a relação pode ser 'maior' ou 'menor' e o valor pode ser qualquer valor numérico.

  • proteína: este parâmetro deve receber um dicionário similar ao parâmetro carboidrato.

Exemplo de utilização:

filtrar_alimentos(categoria=1, carboidrato={'relacao': 'menor', 'valor': 10}, proteina={'relacao': 'maior', 'valor': 20})

Neste caso, a função deve retornar todos os alimentos da categoria 1 que tem menos que 10 gramas de carboidrato e mais que 20 gramas de proteína. O retorno precisa ser uma lista com o seguinte formato:

[
    {'alimento': 'Descricao', 'carboidrato': N, 'proteina': M},
    {'alimento': 'Descricao', 'carboidrato': N, 'proteina': M},
    ...
]

Se não existirem alimentos que satisfaçam as restrições então a lista deve vir vazia.

Alguns alimentos não tem o valor para carboidrato ou para proteína. A função deve ignorar estes casos. O mesmo para situações onde são apresentados valores não numéricos.