Trilhas
/
jq
jq
/
Exercícios
/
Placar de Recordes
Placar de Recordes

Placar de Recordes

Exercício de aprendizagem

Introdução

Objetos

Um objeto JSON é, usando a terminologia de outras linguagens, um "hash", um "mapa" ou um "dicionário".

O JSON define um objeto como:

Um objeto é um conjunto não ordenado de pares nome/valor. Um objeto começa com { chave de abertura e termina com } chave de fechamento. Cada nome é seguido de : dois-pontos e os pares nome/valor são separados por , vírgula.

O nome precisa ser uma string. Outra palavra para nome é chave.

O valor pode ser de qualquer tipo JSON. Diferentes valores no mesmo objeto podem ser de tipos diferentes, como neste exemplo.

{
  "name": "Jane",
  "age": 42,
  "pets": ["cat", "fish"],
  "address": {"street": "123 Main St", "city": "Springfield"}
}

Observe que não pode haver uma vírgula depois do último par chave-valor.

Criando objetos

Use chaves para reunir os pares nome/valor. Embora os nomes precisem ser strings, eles não precisam estar entre aspas se forem parecidos com identificadores (compostos de caracteres alfanuméricos e underline, e que não começam com um dígito).

{name: "Jane", age: 42}

É válido usar chaves que não sejam parecidas com identificadores. Basta colocá-las entre aspas.

{"first name": "Jane", "last name": "Lopez", age: 42}

Se o nome for o resultado de uma expressão, a expressão precisa estar entre parênteses.

$ echo "Jane" | jq -Rc '{.: 42}'
# verbose error message ...

$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}

Indexação

Os valores são obtidos de um objeto com notação de ponto.

{name: "Jane", age: 42} | .age    # => 42

Se você não puder se referir à chave como um identificador, use notação de colchetes.

"name" as $key | {name: "Jane", age: 42} | .$key    # => error
"name" as $key | {name: "Jane", age: 42} | .[$key]  # => "Jane"

Adicionando ou alterando pares chave-valor

Para adicionar um novo par chave-valor a um array, ou para atualizar o valor de uma chave existente, use o operador de atribuição =, com uma expressão de índice do lado esquerdo.

{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
#      "name": "Jane",
#      "age": 21,
#      "sport": "tennis"
#    }

O operador + vai mesclar objetos.

{Richard: 54} + {Jane: 42}
# => {
#      "Richard": 54,
#      "Jane": 42
#    }

Removendo uma chave

Use a função del para remover uma chave. Ela retorna o objeto atualizado.

{name: "Jane", age: 42} | del(.age)   # => {"name": "Jane"}

O parâmetro de del é uma expressão de índice (usando notação de ponto ou de colchetes) que resolve para uma chave no objeto. O jq chama isso de expressão de caminho. Não basta apenas passar uma string.

{name: "Jane", age: 42} | del(name)        # error: name/0 is not defined
{name: "Jane", age: 42} | del("name")      # error: Invalid path expression with result "name"
{name: "Jane", age: 42} | del(.name)       # OK
{name: "Jane", age: 42} | del(.["name"])   # OK

Pertencimento

  • Para testar se o objeto tem uma chave, use a função has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Teste se uma chave está em um objeto com in.

    {name: "Jane", age: 42} as $example
    |
      ("name"  | in($example)),    # => true
      ("sport" | in($example))     # => false
    

Listar todas as chaves

Use a função keys para produzir uma lista com todas as chaves.

{name: "Jane", age: 42} | keys   # => ["age", "name"]

Observe que keys vai ordenar as chaves. Para obter as chaves na ordem original, use keys_unsorted.

Não existe uma função equivalente para listar todos os valores. Porém, o filtro .[] produz os valores do objeto como um stream, e esse stream pode ser capturado com o construtor de array [...].

[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]

Iterando

  • A função map_values(filter) aplica o filtro a cada valor no objeto.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Para iterar sobre um objeto, primeiro precisamos convertê-lo em um array de objetos chave-valor. A função to_entries faz isso.

    {name: "Jane", age: 42} | to_entries'
    # => [
    #      {
    #        "key": "name",
    #        "value": "Jane"
    #      },
    #      {
    #        "key": "age",
    #        "value": 42
    #      }
    #    ]
    

    Nesse ponto, podemos usar funções de iteração de array, como map.

  • A função from_entries é o inverso: converte um array de objetos chave-valor em um objeto.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # =>{"name": "Jane", "age": 42}
    
  • Para aplicar um filtro a cada par chave-valor em um objeto, use a função with_entries(filter).

    Por exemplo, dado um objeto que mapeia um nome para uma idade, as chaves e os valores podem ser trocados da seguinte forma.

    {"Jane": 42, "Richard": 54}
    | with_entries({key: (.value | tostring), value: .key})
    

    produz

    {
      "42": "Jane",
      "54": "Richard"
    }
    

    with_entries(filter) é o mesmo que

    to_entries | map(filter) | from_entries
    

Instruções

Neste exercício, você vai implementar uma forma de acompanhar os recordes do jogo mais popular do fliperama da sua região.

Você tem 6 funções para implementar, a maioria relacionada a manipular um objeto que guarda os recordes.

1. Criar um novo placar de recordes

Escreva uma função create_score_board que cria um objeto que serve como placar de recordes. As chaves desse objeto serão os nomes dos jogadores, e os valores serão as pontuações deles. Para fins de teste, você quer incluir diretamente uma entrada no objeto. Essa entrada inicial deve ter "The Best Ever" como nome do jogador e 1000000 como pontuação.

create_score_board
# returns an object with one initial entry

2. Adicionar jogadores a um placar

Para adicionar um jogador ao placar de recordes, implemente a função add_player. Ela recebe um placar como entrada e precisa de dois parâmetros: o nome do jogador e a pontuação dele. A função retorna o objeto do placar com o novo jogador adicionado.

{"José Valim", 486373}
| add_player("Dave Thomas"; 0)
# => {"Dave Thomas": 0, "José Valim": 486373} -- in some order

Se o jogador já estiver no placar, retorne o placar sem alterações.

3. Remover jogadores de um placar

Se os jogadores violarem as regras do fliperama, eles são removidos manualmente do placar de recordes. Implemente remove_player, que recebe um placar como entrada e um parâmetro, o nome do jogador a remover. Essa função deve remover a entrada do jogador indicado do placar e retornar o novo placar. Se o jogador não estivesse no placar, nada deve acontecer com o placar; ele deve ser retornado como está.

{"Dave Thomas": 0} | remove_player("Dave Thomas")
# => {}

{"Dave Thomas": 0} | remove_player("Rose Fanaras")
# => {"Dave Thomas": 0}

4. Aumentar a pontuação de um jogador

Se um jogador terminar outra partida no fliperama, uma certa quantidade de pontos será adicionada à pontuação anterior no placar. Implemente update_score, que recebe um placar como entrada e precisa de dois parâmetros: o nome do jogador e a quantidade de pontos a adicionar. A função deve retornar o placar depois que a atualização for feita.

{"Freyja Ćirić": 12771000} | update_score("Freyja Ćirić"; 73)
# => {"Freyja Ćirić": 12771073}

Essa função deve adicionar o jogador ao placar se ele ainda não estiver lá.

5. Aplicar os pontos de bônus de segunda-feira

O fliperama mantém um placar separado às segundas-feiras. No fim do dia, cada jogador nesse placar ganha 100 pontos adicionais.

Implemente a função apply_monday_bonus. A função adiciona os pontos de bônus para cada jogador listado nesse placar.

{
  "Dave Thomas": 44,
  "Freyja Ćirić": 539,
  "José Valim": 265
}
| apply_monday_bonus
# => {"Dave Thomas": 144, "Freyja Ćirić": 639, "José Valim": 365}

6. Encontrar a pontuação total

Fliperamas diferentes competem entre si para determinar quem tem os melhores jogadores. O fliperama com a maior pontuação total ganha a honra.

Escreva uma função total_score. Ela recebe um placar como entrada e retorna a soma das pontuações de todos os jogadores.

{
  "Dave Thomas": 44,
  "Freyja Ćirić": 539,
  "José Valim": 265
}
| total_score
# => 848
Editar via GitHub O link abre em uma nova janela ou aba
jq Exercism

Tudo pronto para começar Placar de Recordes?

Crie sua conta no Exercism para aprender e dominar jq com 12 conceitos75 exercícios e mentoria humana de verdade, tudo de graça.