Parcours
/
jq
jq
/
Exercices
/
Tableau des meilleurs scores
Tableau des meilleurs scores

Tableau des meilleurs scores

Exercice d'apprentissage

Introduction

Objets

Un objet JSON est, pour reprendre la terminologie d'autres langages, un « hash », une « map » ou un « dictionnaire ».

JSON définit un objet comme suit :

Un objet est un ensemble non ordonné de paires nom/valeur. Un objet commence par une accolade ouvrante { et se termine par une accolade fermante }. Chaque nom est suivi de deux-points : et les paires nom/valeur sont séparées par une virgule ,.

Le nom doit être une string. Un autre mot pour nom est clé.

La valeur peut être de n'importe quel type JSON. Des valeurs différentes dans un même objet peuvent être de types différents, comme dans cet exemple.

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

Note qu'il ne doit pas y avoir de virgule après la dernière paire clé-valeur.

Crée des objets

Utilise des accolades pour rassembler les paires nom/valeur. Même si les noms doivent être des strings, il n'est pas nécessaire de les mettre entre guillemets s'ils sont de type identifiant (composés de caractères alphanumériques et de tiret bas, et qui ne commencent pas par un chiffre).

{name: "Jane", age: 42}

Il est tout à fait valide d'utiliser des clés qui ne sont pas de type identifiant. Mets-les simplement entre guillemets.

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

Si le nom est le résultat d'une expression, l'expression doit être mise entre parenthèses.

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

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

Indexation

On récupère les valeurs d'un objet avec la notation pointée.

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

Si tu ne peux pas désigner la clé comme un identifiant, utilise la notation par crochets.

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

Ajoute ou modifie des paires clé-valeur

Pour ajouter une nouvelle paire clé-valeur à un tableau, ou pour mettre à jour la valeur d'une clé existante, utilise l'opérateur d'affectation =, avec une expression d'indice à gauche.

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

L'opérateur + fusionne des objets.

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

Supprime une clé

Utilise la fonction del pour supprimer une clé. Elle renvoie l'objet mis à jour.

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

Le paramètre de del est une expression d'indice (en notation pointée ou par crochets) qui se résout en une clé de l'objet. jq l'appelle une expression de chemin. Il ne suffit pas de donner une simple 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

Appartenance

  • Pour tester si l'objet possède une clé, utilise la fonction has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Teste si une clé est dans un objet avec in.

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

Liste toutes les clés

Utilise la fonction keys pour afficher la liste de toutes les clés.

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

Note que keys va trier les clés. Pour récupérer les clés dans l'ordre d'origine, utilise keys_unsorted.

Il n'existe pas de fonction équivalente pour lister toutes les valeurs. Cependant, le filtre .[] produit les valeurs de l'objet sous forme de flux, et ce flux peut être capturé avec le constructeur de tableau [...].

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

Itération

  • La fonction map_values(filter) applique le filtre à chaque valeur de l'objet.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Pour itérer sur un objet, il faut d'abord le convertir en un tableau d'objets clé-valeur. C'est ce que fait la fonction to_entries.

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

    À ce stade, on peut utiliser les fonctions d'itération sur les tableaux, comme map.

  • La fonction from_entries fait l'inverse : convertir un tableau d'objets clé-valeur en un objet.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # =>{"name": "Jane", "age": 42}
    
  • Pour appliquer un filtre à chaque paire clé-valeur d'un objet, utilise la fonction with_entries(filter).

    Par exemple, étant donné un objet qui associe un nom à un âge, on peut échanger les clés et les valeurs comme suit.

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

    produit

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

    with_entries(filter) équivaut à

    to_entries | map(filter) | from_entries
    

Instructions

Dans cet exercice, tu vas implémenter un moyen de garder la trace des meilleurs scores du jeu le plus populaire de la salle d'arcade près de chez toi.

Tu as 6 fonctions à implémenter, qui servent principalement à manipuler un objet contenant les meilleurs scores.

1. Crée un nouveau tableau des meilleurs scores

Écris une fonction create_score_board qui crée un objet qui sert de tableau des meilleurs scores. Les clés de cet objet seront les noms des joueurs, et les valeurs, leurs scores. Pour les besoins des tests, on souhaite inclure directement une entrée dans l'objet. Cette entrée initiale doit être composée de "The Best Ever" comme nom de joueur et de 1000000 comme score.

create_score_board
# returns an object with one initial entry

2. Ajoute des joueurs à un tableau des meilleurs scores

Pour ajouter un joueur au tableau des meilleurs scores, implémente la fonction add_player. Elle prend un tableau des meilleurs scores en entrée et nécessite deux paramètres : le nom du joueur et le score du joueur. La fonction renvoie le tableau des meilleurs scores avec le nouveau joueur ajouté.

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

Si le joueur est déjà sur le tableau, renvoie le tableau inchangé.

3. Retire des joueurs d'un tableau des meilleurs scores

Si des joueurs enfreignent les règles de la salle d'arcade, ils sont retirés manuellement du tableau des meilleurs scores. Implémente remove_player, qui prend un tableau en entrée et un paramètre : le nom du joueur à retirer. Cette fonction doit supprimer du tableau l'entrée du joueur donné et renvoyer le nouveau tableau. Si le joueur n'était pas déjà sur le tableau, rien ne doit changer : le tableau doit être renvoyé tel quel.

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

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

4. Augmente le score d'un joueur

Si un joueur termine une autre partie à la salle d'arcade, un certain nombre de points s'ajoutent au score précédent du tableau. Implémente update_score, qui prend un tableau des meilleurs scores en entrée et nécessite deux paramètres : le nom du joueur et le nombre de points à ajouter. La fonction doit renvoyer le tableau des meilleurs scores une fois la mise à jour effectuée.

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

Cette fonction doit ajouter le joueur au tableau s'il n'y était pas déjà.

5. Applique les points bonus du lundi

La salle d'arcade tient un tableau des scores séparé le lundi. À la fin de la journée, chaque joueur de ce tableau reçoit 100 points supplémentaires.

Implémente la fonction apply_monday_bonus. La fonction ajoute les points bonus à chaque joueur inscrit sur ce tableau.

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

6. Trouve le score total

Différentes salles d'arcade s'affrontent pour déterminer qui a les meilleurs joueurs. La salle d'arcade avec le score total le plus élevé remporte l'honneur.

Écris une fonction total_score. Elle prend un tableau des meilleurs scores en entrée et renvoie la somme des scores de tous les joueurs.

{
  "Dave Thomas": 44,
  "Freyja Ćirić": 539,
  "José Valim": 265
}
| total_score
# => 848
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
jq Exercism

Prêt à commencer Tableau des meilleurs scores ?

Inscris-toi sur Exercism pour apprendre et maîtriser jq avec 12 concepts75 exercices, et un vrai mentorat humain, le tout gratuitement.