Rutas
/
jq
jq
/
Ejercicios
/
Tabla de puntuaciones
Tabla de puntuaciones

Tabla de puntuaciones

Ejercicio de aprendizaje

Introducción

Objetos

Un objeto JSON es, por usar terminología de otros lenguajes, un «hash», un «map» o un «diccionario».

JSON define un objeto así:

Un objeto es un conjunto no ordenado de pares nombre/valor. Un objeto empieza con {, llave izquierda, y termina con }, llave derecha. Cada nombre va seguido de : (dos puntos) y los pares nombre/valor se separan con , (coma).

El nombre debe ser un string. Otra palabra para nombre es clave.

El valor puede ser de cualquier tipo de JSON. Distintos valores dentro del mismo objeto pueden ser de tipos diferentes, como en este ejemplo.

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

Ten en cuenta que no debe haber una coma después del último par clave-valor.

Crear objetos

Usa llaves para agrupar los pares nombre/valor. Aunque los nombres deben ser strings, no hace falta entrecomillarlos si son similares a un identificador (están formados por caracteres alfanuméricos y guiones bajos, y no empiezan por un dígito).

{name: "Jane", age: 42}

Es válido usar claves que no sean similares a un identificador. Solo tienes que entrecomillarlas.

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

Si el nombre es el resultado de una expresión, la expresión debe ir entre paréntesis.

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

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

Indexación

Los valores se obtienen de un objeto con la notación de punto.

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

Si no puedes referirte a la clave como un identificador, usa la notación de corchetes.

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

Añadir o cambiar pares clave-valor

Para añadir un nuevo par clave-valor a un array, o para actualizar el valor de una clave existente, usa el operador de asignación =, con una expresión de índice en el lado izquierdo.

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

El operador + fusiona objetos.

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

Eliminar una clave

Usa la función del para eliminar una clave. Devuelve el objeto actualizado.

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

El parámetro de del es una expresión de índice (con notación de punto o de corchetes) que se resuelve en una clave del objeto. jq la llama expresión de ruta. No basta con dar simplemente un 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

Pertenencia

  • Para comprobar si el objeto tiene una clave, usa la función has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Comprueba si una clave está en un objeto con in.

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

Enumerar todas las claves

Usa la función keys para obtener un array con todas las claves.

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

Ten en cuenta que keys ordena las claves. Para obtener las claves en el orden original, usa keys_unsorted.

No hay ninguna función equivalente para enumerar todos los valores. Sin embargo, el filtro .[] genera los valores del objeto como un flujo, y ese flujo se puede capturar con el constructor de arrays [...].

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

Iterar

  • La función map_values(filter) aplica el filtro a cada valor del objeto.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Para iterar sobre un objeto, primero tenemos que convertirlo en un array de objetos clave-valor. La función to_entries hace eso.

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

    En este punto, podemos usar funciones de iteración de arrays, como map.

  • La función from_entries es la inversa: convierte un array de objetos clave-valor en un objeto.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # =>{"name": "Jane", "age": 42}
    
  • Para aplicar un filtro a cada par clave-valor de un objeto, usa la función with_entries(filter).

    Por ejemplo, dado un objeto que asocia un nombre a una edad, las claves y los valores se pueden intercambiar así.

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

    produce

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

    with_entries(filter) es lo mismo que

    to_entries | map(filter) | from_entries
    

Instrucciones

En este ejercicio, vas a implementar una forma de llevar un registro de las puntuaciones más altas del juego más popular de tu salón recreativo local.

Tienes 6 funciones que implementar, en su mayoría relacionadas con la manipulación de un objeto que contiene puntuaciones altas.

1. Crea una nueva tabla de puntuaciones altas

Escribe una función create_score_board que cree un objeto que sirva como tabla de puntuaciones altas. Las claves de este objeto serán los nombres de los jugadores y los valores serán sus puntuaciones. Para las pruebas, quieres incluir directamente una entrada en el objeto. Esta entrada inicial debe constar de "The Best Ever" como nombre del jugador y 1000000 como puntuación.

create_score_board
# returns an object with one initial entry

2. Añade jugadores a una tabla de puntuaciones

Para añadir un jugador a la tabla de puntuaciones altas, implementa la función add_player. Toma una tabla de puntuaciones como entrada y necesita dos parámetros: el nombre del jugador y la puntuación del jugador. La función devuelve el objeto tabla de puntuaciones con el nuevo jugador añadido.

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

Si el jugador ya está en la tabla, devuelve la tabla sin cambios.

3. Elimina jugadores de una tabla de puntuaciones

Si los jugadores infringen las normas del salón recreativo, se eliminan manualmente de la tabla de puntuaciones altas. Implementa remove_player, que toma una tabla como entrada y un parámetro: el nombre del jugador que se va a eliminar. Esta función debe eliminar la entrada del jugador indicado de la tabla y devolver la nueva tabla. Si el jugador no estaba en la tabla en primer lugar, no debe pasar nada con la tabla; debe devolverse tal cual.

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

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

4. Aumenta la puntuación de un jugador

Si un jugador termina otra partida en el salón recreativo, se añadirá una cierta cantidad de puntos a la puntuación anterior en la tabla. Implementa update_score, que toma una tabla de puntuaciones como entrada y necesita dos parámetros: el nombre del jugador y la cantidad de puntuación que se va a añadir. La función debe devolver la tabla de puntuaciones después de realizar la actualización.

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

Esta función debe añadir al jugador a la tabla si aún no estaba en ella.

5. Aplica los puntos de bonificación de los lunes

El salón recreativo mantiene una tabla de puntuaciones separada los lunes. Al final del día, cada jugador de esa tabla obtiene 100 puntos adicionales.

Implementa la función apply_monday_bonus. La función añade los puntos de bonificación a cada jugador que figura en esa tabla.

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

6. Encuentra la puntuación total

Diferentes salones recreativos compiten entre sí para determinar quién tiene los mejores jugadores. El salón recreativo con la puntuación total más alta gana el honor.

Escribe una función total_score. Toma una tabla de puntuaciones como entrada y devuelve la suma de las puntuaciones de todos los jugadores.

{
  "Dave Thomas": 44,
  "Freyja Ćirić": 539,
  "José Valim": 265
}
| total_score
# => 848
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
jq Exercism

¿Listo para empezar Tabla de puntuaciones?

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