Rutas
/
jq
jq
/
Ejercicios
/
Estadísticas de notas
Estadísticas de notas

Estadísticas de notas

Ejercicio de aprendizaje

Introducción

Reduce

Supongamos que queremos sumar un array de números. Hay muchas formas de lograr este objetivo.

  • En muchos lenguajes, este problema se expresa como un bucle con una variable acumuladora.

  • Este problema se puede escribir como una función recursiva. En pseudocódigo, podríamos tener algo así.

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

    Este método de dividir el problema en partes más pequeñas también se puede describir como «reducir hacia el caso base».

Reduce es una forma de combinar todos los elementos de una estructura de datos en un único valor. El proceso itera sobre la estructura de datos, aplicando una función a cada elemento para actualizar el resultado acumulado.

En jq, este proceso se implementa en el filtro reduce. En otros lenguajes, puede llamarse «fold», «fold-left», «inject» o «aggregate».

La expresión reduce de jq tiene este aspecto.

reduce STREAM_EXPRESSION as $var (INITIAL_VALUE; UPDATE_EXPRESSION)
  • STREAM_EXPRESSION es un stream de elementos, cada uno almacenado a su vez en la variable $var.
    • Recuerda que, para obtener un stream a partir de un array, usa el filtro iterador .[]: $myArray | .[].
  • INITIAL_VALUE es el valor inicial del resultado acumulado (conocido como el «acumulador»).
  • UPDATE_EXPRESSION combina («pliega») el valor actual ($var) con el acumulador.
    • En el contexto de esta expresión, . es el valor del acumulador.
    • La salida de la expresión se almacena en el acumulador para usarla en la siguiente iteración.
    • Tras la última iteración, el resultado acumulado es la salida de reduce.

Veamos un ejemplo: sumar los números de un array. El filtro add hace exactamente esto, pero vamos a ver cómo implementarlo.

Si usamos [10, 20, 30, 40] como entrada y tomamos cero como estado inicial, así se ve cada paso.

# estado elemento reductor resultado
1 0 10 0 + 10 10
2 10 20 10 + 20 30
3 30 30 30 + 30 60
4 60 40 60 + 40 100

En la sintaxis de jq, esto tiene este aspecto.

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

Podemos expresarlo con el filtro reduce.

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

En realidad, la función integrada add está implementada con reduce, pero usa «null» como estado inicial (a cualquier tipo de datos se le puede sumar null).

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

Algunas cosas que tener en cuenta

  • En la expresión de reducción, . es el acumulador. Si la entrada es un objeto al que necesitas hacer referencia dentro de la función reductora, tienes que guardarlo en una variable.

    {"apple": 10, "banana": 16, "carrot": 4}
    | . as $obj
    | reduce (keys | .[]) as $key (0; . + $obj[$key])     # => 30
    
  • El acumulador puede ser de cualquier tipo de dato. Por ejemplo, puede que quieras invertir un array.

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

Instrucciones

Eres docente. Al final del año, has generado una nota numérica para cada uno de tus estudiantes. Ahora tienes que traducir esa nota a una nota con letra y contar cuántos estudiantes han obtenido cada nota con letra.

1. Traduce una nota numérica a una nota con letra

La función letter_grade recibe como entrada una nota numérica y devuelve la letra. Usa estos rangos:

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

Ejemplo:

75 | letter_grade   # => "C"

2. Cuenta el número de estudiantes para cada nota con letra

La función count_letter_grades recibe un objeto que asocia los nombres de los estudiantes con sus notas. La salida será un objeto que asocia cada nota con letra con el número de estudiantes que tienen esa nota.

Ejemplo:

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

Hay varias formas distintas de resolver esto. Usa el filtro reduce para practicar.

Editar en GitHub El enlace se abre en una ventana o pestaña nueva
jq Exercism

¿Listo para empezar Estadísticas de notas?

Regístrate en Exercism para aprender y dominar jq con 12 conceptos75 ejercicios y mentoría humana real, todo gratis.