Tracks
/
jq
jq
/
Übungen
/
Notenstatistik
Notenstatistik

Notenstatistik

Lernübung

Einführung

Reduzieren

Angenommen, wir möchten ein Array von Zahlen summieren. Es gibt viele Möglichkeiten, dieses Ziel zu erreichen.

  • In vielen Sprachen drückt man dieses Problem als Schleife mit einer Akkumulatorvariable aus.

  • Man kann dieses Problem als rekursive Funktion schreiben. In Pseudocode könnte das so aussehen.

    function Add(X, Sum=0):
      if X is empty then
        return Sum
      else
        return Add(rest(X), Sum + first(X))
      end
    end
    

    Diese Methode, das Problem in kleinere Teile zu zerlegen, kann man auch als „Reduzieren auf den Basisfall“ beschreiben.

Reduzieren ist eine Möglichkeit, alle Elemente einer Datenstruktur zu einem einzigen Wert zusammenzufassen. Der Prozess iteriert über die Datenstruktur und wendet auf jedes Element eine Funktion an, um das akkumulierte Ergebnis zu aktualisieren.

In jq ist dieser Prozess im reduce-Filter implementiert. In anderen Sprachen wird es vielleicht „fold“, „fold-left“, „inject“ oder „aggregate“ genannt.

Der reduce-Ausdruck in jq sieht so aus.

reduce STREAM_EXPRESSION as $var (INITIAL_VALUE; UPDATE_EXPRESSION)
  • STREAM_EXPRESSION ist ein Stream von Elementen, die nacheinander in der Variable $var gespeichert werden.
    • Zur Erinnerung: Um ein Array zu streamen, verwendest du den Iterator-Filter .[]: $myArray | .[].
  • INITIAL_VALUE ist der Startwert des akkumulierten Ergebnisses (bekannt als der „Akkumulator“).
  • Der UPDATE_EXPRESSION kombiniert („faltet“) den aktuellen Wert ($var) in den Akkumulator.
    • Im Kontext dieses Ausdrucks ist . der Wert des Akkumulators.
    • Die Ausgabe des Ausdrucks wird für die nächste Iteration im Akkumulator gespeichert.
    • Nach der letzten Iteration ist das akkumulierte Ergebnis die Ausgabe von reduce.

Schauen wir uns ein Beispiel an: die Zahlen in einem Array addieren. Der Filter add macht genau das, aber wir werden sehen, wie man ihn implementiert.

Wenn wir [10, 20, 30, 40] als Eingabe verwenden und null als Anfangszustand nehmen, sieht jeder Schritt so aus.

# Zustand Element Reducer Ergebnis
1 0 10 0 + 10 10
2 10 20 10 + 20 30
3 30 30 30 + 30 60
4 60 40 60 + 40 100

In der jq-Syntax sieht das wie dieser Code aus.

0 + 10 | . + 20 | . + 30 | . + 40

Wir können das mit dem reduce-Filter ausdrücken.

[10, 20, 30, 40] | reduce .[] as $n (0; . + $n)     # => 100
Note

Das eingebaute add ist tatsächlich mit reduce implementiert, verwendet aber „null“ als Anfangszustand (jeder Datentyp kann zu null addiert werden).

def add: reduce .[] as $x (null; . + $x);

Ein paar Dinge, die du beachten solltest

  • Im reduzierenden Ausdruck ist . der Akkumulator. Wenn die Eingabe ein Objekt ist, auf das du innerhalb der reduzierenden Funktion verweisen musst, musst du es in einer Variable speichern.

    {"apple": 10, "banana": 16, "carrot": 4}
    | . as $obj
    | reduce (keys | .[]) as $key (0; . + $obj[$key])     # => 30
    
  • Der Akkumulator kann von jedem Datentyp sein. Zum Beispiel möchtest du vielleicht ein Array umkehren.

    ["A", "B", "C", "D"]
    | reduce .[] as $elem ([]; [$elem] + .)       # => ["D", "C", "B", "A"]
    

Anleitung

Du bist Lehrer. Am Ende des Jahres hast du für jeden deiner Schüler eine Note als Zahl erzeugt. Jetzt musst du diese in eine Buchstabennote umwandeln und zählen, wie viele Schüler jede Buchstabennote erreicht haben

1. Eine Note als Zahl in eine Buchstabennote umwandeln

Die Funktion letter_grade nimmt eine Note als Zahl entgegen und gibt den Buchstaben aus. Verwende diese Bereiche:

Buchstabe Note
A 90% - 100%
B 80% - 89%
C 70% - 79%
D 60% - 69%
F 0% - 59%

Beispiel:

75 | letter_grade   # => "C"

2. Die Anzahl der Schüler für jede Buchstabennote zählen

Die Funktion count_letter_grades nimmt ein Objekt entgegen, das Schülernamen ihren Noten zuordnet. Die Ausgabe ist ein Objekt, das jeder Buchstabennote die Anzahl der Schüler mit dieser Note zuordnet.

Beispiel:

{"Joe": 78, "Jane": 93, "Richard": 72} | count_letter_grades
# => {"A": 1, "B": 0, "C": 2, "D": 0, "F": 0}

Es gibt mehrere Möglichkeiten, das zu lösen. Verwende zum Üben den reduce-Filter.

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
jq Exercism

Bereit, mit Notenstatistik zu starten?

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