Track
/
jq
jq
/
Esercizi
/
Statistiche dei voti
Statistiche dei voti

Statistiche dei voti

Esercizio di apprendimento

Introduzione

Riduzione

Supponiamo di voler sommare un array di numeri. Ci sono molti modi per raggiungere questo obiettivo.

  • In molti linguaggi, questo problema si esprime con un ciclo ed una variabile accumulatore.

  • Questo problema si può scrivere come funzione ricorsiva. In pseudo-codice, potremmo avere questo.

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

    Questo metodo di suddividere il problema in pezzi più piccoli si può descrivere anche come «ridurre verso il caso base».

La riduzione è un modo per combinare tutti gli elementi di una struttura dati in un unico valore. Il processo esegue un'iterazione sulla struttura dati, applicando una funzione ad ogni elemento per aggiornare il risultato accumulato.

In jq, questo processo è implementato nel filtro reduce. In altri linguaggi, può essere chiamato "fold", "fold-left", "inject" o "aggregate".

L'espressione reduce di jq si presenta così.

reduce STREAM_EXPRESSION as $var (INITIAL_VALUE; UPDATE_EXPRESSION)
  • STREAM_EXPRESSION è uno stream di elementi, ciascuno memorizzato a turno nella variabile $var.
  • INITIAL_VALUE è il valore iniziale del risultato accumulato (noto come «accumulatore»).
  • UPDATE_EXPRESSION combina («fold») il valore corrente ($var) nell'accumulatore.
    • Nel contesto di questa espressione, . è il valore dell'accumulatore.
    • L'output dell'espressione viene memorizzato nell'accumulatore ed usato nell'iterazione successiva.
    • Dopo l'ultima iterazione, il risultato accumulato è l'output di reduce.

Vediamo un esempio: sommare i numeri di un array. Il filtro add fa proprio questo, ma vedremo come implementarlo.

Se usiamo [10, 20, 30, 40] come input e prendiamo zero come stato iniziale, ecco come si presenta ogni passo.

# stato elemento riduttore risultato
1 0 10 0 + 10 10
2 10 20 10 + 20 30
3 30 30 30 + 30 60
4 60 40 60 + 40 100

Nella sintassi di jq, si presenta come questo codice.

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

Possiamo esprimere la stessa cosa con il filtro reduce.

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

La funzione incorporata add in realtà è implementata con reduce, ma usa "null" come stato iniziale (a null si può sommare qualsiasi tipo di dato).

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

Alcune cose da tenere a mente

  • Nell'espressione di riduzione, . è l'accumulatore. Se l'input è un oggetto che devi referenziare all'interno della funzione di riduzione, devi memorizzarlo in una variabile.

    {"apple": 10, "banana": 16, "carrot": 4}
    | . as $obj
    | reduce (keys | .[]) as $key (0; . + $obj[$key])     # => 30
    
  • L'accumulatore può essere di qualsiasi tipo di dato. Per esempio, potresti voler invertire un array.

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

Istruzioni

Sei un insegnante. Alla fine dell'anno hai assegnato un voto numerico a ciascuno dei tuoi studenti. Ora devi convertire quel voto in un voto in lettere e contare quanti studenti hanno ottenuto ciascun voto.

1. Converti un voto numerico in un voto in lettere

La funzione letter_grade prende in input un voto numerico e produce in output la lettera. Usa questi intervalli:

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

Esempio:

75 | letter_grade   # => "C"

2. Conta il numero di studenti per ogni voto in lettere

La funzione count_letter_grades prende un oggetto che mappa i nomi degli studenti ai loro voti. L'output sarà un oggetto che mappa ogni voto in lettere al numero di studenti con quel voto.

Esempio:

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

Ci sono diversi modi per risolvere questo problema. Usa il filtro reduce per esercitarti.

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
jq Exercism

Vuoi iniziare Statistiche dei voti?

Iscriviti a Exercism per imparare e padroneggiare jq con 12 concetti75 esercizi e il mentoring di persone reali, tutto gratis.