Tracks
/
jq
jq
/
Übungen
/
Bestenliste
Bestenliste

Bestenliste

Lernübung

Einführung

Objekte

Ein JSON-Objekt ist, um die Terminologie anderer Sprachen zu verwenden, ein „Hash“, eine „Map“ oder ein „Wörterbuch“.

JSON definiert ein Objekt wie folgt:

Ein Objekt ist eine ungeordnete Menge von Name/Wert-Paaren. Ein Objekt beginnt mit { (linke geschweifte Klammer) und endet mit } (rechte geschweifte Klammer). Auf jeden Namen folgt ein : (Doppelpunkt), und die Name/Wert-Paare werden durch ein , (Komma) getrennt.

Der Name muss ein String sein. Ein anderes Wort für Name ist Schlüssel.

Der Wert kann von jedem beliebigen JSON-Typ sein. Verschiedene Werte im selben Objekt können von unterschiedlichen Typen sein, wie in diesem Beispiel.

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

Beachte, dass nach dem letzten Schlüssel-Wert-Paar kein Komma stehen darf.

Objekte erstellen

Verwende geschweifte Klammern, um die Name/Wert-Paare zu sammeln. Auch wenn die Namen Strings sein müssen, müssen sie nicht in Anführungszeichen gesetzt werden, wenn die Namen bezeichnerähnlich sind (sie bestehen aus alphanumerischen Zeichen und dem Unterstrich und beginnen nicht mit einer Ziffer).

{name: "Jane", age: 42}

Es ist gültig, Schlüssel zu verwenden, die nicht bezeichnerähnlich sind. Setze sie einfach in Anführungszeichen.

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

Wenn der Name das Ergebnis eines Ausdrucks ist, muss der Ausdruck in runde Klammern gesetzt werden.

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

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

Indizierung

Werte werden mit der Punktnotation aus einem Objekt abgerufen.

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

Wenn du auf den Schlüssel nicht als Bezeichner verweisen kannst, verwende die Klammernotation.

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

Schlüssel-Wert-Paare hinzufügen oder ändern

Um einem Array ein neues Schlüssel-Wert-Paar hinzuzufügen oder den Wert eines vorhandenen Schlüssels zu aktualisieren, verwende den Zuweisungsoperator =, mit einem Indexausdruck auf der linken Seite.

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

Der Operator + wird Objekte zusammenführen.

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

Einen Schlüssel entfernen

Verwende die Funktion del, um einen Schlüssel zu entfernen. Sie gibt das aktualisierte Objekt zurück.

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

Der Parameter von del ist ein Indexausdruck (mit Punkt- oder Klammernotation), der sich zu einem Schlüssel im Objekt auflöst. jq nennt ihn einen Pfadausdruck. Es genügt nicht, einfach einen String anzugeben.

{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

Zugehörigkeit

  • Um zu prüfen, ob ein Objekt einen Schlüssel enthält, verwende die Funktion has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Prüfe mit in, ob ein Schlüssel in einem Objekt enthalten ist.

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

Alle Schlüssel auflisten

Verwende die Funktion keys, um eine Liste aller Schlüssel auszugeben.

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

Beachte, dass keys die Schlüssel sortiert. Um die Schlüssel in der ursprünglichen Reihenfolge abzurufen, verwende keys_unsorted.

Es gibt keine entsprechende Funktion, um alle Werte aufzulisten. Der Filter .[] gibt die Objektwerte jedoch als Stream aus, und dieser Stream kann mit dem Array-Konstruktor [...] erfasst werden.

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

Iterieren

  • Die Funktion map_values(filter) wendet den Filter auf jeden Wert im Objekt an.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Um über ein Objekt zu iterieren, müssen wir es zunächst in ein Array von Schlüssel-Wert-Objekten umwandeln. Die Funktion to_entries erledigt das.

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

    An diesem Punkt können wir Array-Iterationsfunktionen wie map verwenden.

  • Die Funktion from_entries ist die Umkehrung: Sie wandelt ein Array von Schlüssel-Wert-Objekten in ein Objekt um.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # =>{"name": "Jane", "age": 42}
    
  • Um einen Filter auf jedes Schlüssel-Wert-Paar in einem Objekt anzuwenden, verwende die Funktion with_entries(filter).

    Wenn du zum Beispiel ein Objekt hast, das einen Namen auf ein Alter abbildet, kannst du Schlüssel und Werte wie folgt vertauschen.

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

    gibt aus

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

    with_entries(filter) ist dasselbe wie

    to_entries | map(filter) | from_entries
    

Anleitung

In dieser Übung implementierst du eine Möglichkeit, die Höchstpunktzahlen für das beliebteste Spiel in deiner örtlichen Spielhalle zu verwalten.

Du musst 6 Funktionen implementieren, die sich größtenteils mit der Manipulation eines Objekts befassen, das die Höchstpunktzahlen enthält.

1. Erstelle eine neue Bestenliste

Schreibe eine Funktion create_score_board, die ein Objekt erstellt, das als Bestenliste dient. Die Schlüssel dieses Objekts sind die Namen der Spieler, die Werte ihre Punktzahlen. Zu Testzwecken möchtest du direkt einen Eintrag in das Objekt aufnehmen. Dieser anfängliche Eintrag sollte aus "The Best Ever" als Spielername und 1000000 als Punktzahl bestehen.

create_score_board
# returns an object with one initial entry

2. Füge Spieler zu einer Bestenliste hinzu

Um einen Spieler zur Bestenliste hinzuzufügen, implementiere die Funktion add_player. Sie nimmt eine Bestenliste als Eingabe und benötigt zwei Parameter: den Spielernamen und die Punktzahl des Spielers. Die Funktion gibt das Bestenlisten-Objekt mit dem neu hinzugefügten Spieler zurück.

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

Wenn der Spieler bereits auf der Liste steht, gib die Liste unverändert zurück.

3. Entferne Spieler aus einer Bestenliste

Wenn Spieler gegen die Regeln der Spielhalle verstoßen, werden sie manuell aus der Bestenliste entfernt. Implementiere remove_player, die eine Bestenliste als Eingabe und einen Parameter nimmt: den Namen des Spielers, der entfernt werden soll. Diese Funktion soll den Eintrag für den angegebenen Spieler aus der Liste entfernen und die neue Liste zurückgeben. Wenn der Spieler gar nicht auf der Liste stand, soll mit der Liste nichts passieren; sie soll unverändert zurückgegeben werden.

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

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

4. Erhöhe die Punktzahl eines Spielers

Wenn ein Spieler ein weiteres Spiel in der Spielhalle beendet, wird eine bestimmte Anzahl von Punkten zur bisherigen Punktzahl auf der Liste addiert. Implementiere update_score, die eine Bestenliste als Eingabe nimmt und zwei Parameter benötigt: den Spielernamen und die Anzahl der hinzuzufügenden Punkte. Die Funktion soll die Bestenliste nach dem Update zurückgeben.

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

Diese Funktion soll den Spieler zur Liste hinzufügen, wenn er noch nicht darauf stand.

5. Wende die Montags-Bonuspunkte an

Die Spielhalle führt montags eine separate Bestenliste. Am Ende des Tages erhält jeder Spieler auf dieser Liste 100 zusätzliche Punkte.

Implementiere die Funktion apply_monday_bonus. Die Funktion addiert die Bonuspunkte für jeden Spieler, der auf dieser Liste steht.

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

6. Ermittle die Gesamtpunktzahl

Verschiedene Spielhallen treten gegeneinander an, um zu ermitteln, wer die besten Spieler hat. Die Spielhalle mit der höchsten Gesamtpunktzahl gewinnt die Ehre.

Schreibe eine Funktion total_score. Sie nimmt eine Bestenliste als Eingabe und gibt die Summe aller Punktzahlen der Spieler zurück.

{
  "Dave Thomas": 44,
  "Freyja Ćirić": 539,
  "José Valim": 265
}
| total_score
# => 848
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
jq Exercism

Bereit, mit Bestenliste zu starten?

Melde dich bei Exercism an, um jq mit 12 Konzepte75 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.