Διαδρομές
/
jq
jq
/
Ασκήσεις
/
Πίνακας υψηλών βαθμολογιών
Πίνακας υψηλών βαθμολογιών

Πίνακας υψηλών βαθμολογιών

Άσκηση εκμάθησης

Εισαγωγή

Αντικείμενα

Ένα αντικείμενο JSON είναι, για να δανειστούμε ορολογία από άλλες γλώσσες, ένα "hash", ένα "map" ή ένα "dictionary".

Η JSON ορίζει ένα αντικείμενο ως εξής:

Ένα αντικείμενο είναι ένα σύνολο από ζεύγη όνομα/τιμή χωρίς συγκεκριμένη σειρά. Ένα αντικείμενο αρχίζει με { αριστερό άγκιστρο και τελειώνει με } δεξί άγκιστρο. Κάθε όνομα ακολουθείται από : άνω και κάτω τελεία και τα ζεύγη όνομα/τιμή χωρίζονται από , κόμμα.

Το όνομα πρέπει να είναι συμβολοσειρά. Μια άλλη λέξη για το όνομα είναι κλειδί.

Η τιμή μπορεί να είναι οποιουδήποτε τύπου JSON. Διαφορετικές τιμές στο ίδιο αντικείμενο μπορούν να είναι διαφορετικών τύπων, όπως σε αυτό το παράδειγμα.

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

Σημείωσε ότι δεν πρέπει να υπάρχει κόμμα μετά το τελευταίο ζεύγος κλειδιού-τιμής.

Δημιουργία αντικειμένων

Χρησιμοποίησε άγκιστρα για να συγκεντρώσεις τα ζεύγη ονόματος/τιμής. Παρόλο που τα ονόματα πρέπει να είναι συμβολοσειρές, δεν χρειάζεται να μπουν σε εισαγωγικά αν έχουν μορφή αναγνωριστικού (αποτελούνται από αλφαριθμητικούς χαρακτήρες και κάτω παύλα και δεν ξεκινούν με ψηφίο).

{name: "Jane", age: 42}

Είναι έγκυρο να χρησιμοποιήσεις κλειδιά που δεν έχουν μορφή αναγνωριστικού. Απλώς βάλε τα σε εισαγωγικά.

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

Αν το όνομα είναι το αποτέλεσμα μιας έκφρασης, η έκφραση πρέπει να είναι μέσα σε παρενθέσεις.

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

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

Πρόσβαση με θέση

Οι τιμές ανακτώνται από ένα αντικείμενο με συμβολισμό τελείας.

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

Αν δεν μπορείς να αναφερθείς στο κλειδί ως αναγνωριστικό, χρησιμοποίησε συμβολισμό με αγκύλες.

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

Προσθήκη ή αλλαγή ζευγών κλειδιού-τιμής

Για να προσθέσεις ένα νέο ζεύγος κλειδιού-τιμής σε έναν πίνακα ή να ενημερώσεις την τιμή ενός υπάρχοντος κλειδιού, χρησιμοποίησε τον τελεστή ανάθεσης =, με μια έκφραση θέσης στην αριστερή πλευρά.

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

Ο τελεστής + θα συγχωνεύσει τα αντικείμενα.

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

Αφαίρεση κλειδιού

Χρησιμοποίησε τη συνάρτηση del για να αφαιρέσεις ένα κλειδί. Επιστρέφει το ενημερωμένο αντικείμενο.

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

Η παράμετρος της del είναι μια έκφραση θέσης (με συμβολισμό τελείας ή αγκυλών) που αντιστοιχεί σε ένα κλειδί του αντικειμένου. Η jq την ονομάζει έκφραση διαδρομής. Δεν αρκεί να δώσεις απλώς μια συμβολοσειρά.

{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

Ιδιότητα μέλους

  • Για να ελέγξεις αν το αντικείμενο έχει ένα κλειδί, χρησιμοποίησε τη συνάρτηση has.

    {name: "Jane", age: 42} as $example
    |
      ($example | has("name")),    # => true
      ($example | has("sport"))    # => false
    
  • Έλεγξε αν ένα κλειδί βρίσκεται σε ένα αντικείμενο με το in.

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

Εμφάνιση όλων των κλειδιών

Χρησιμοποίησε τη συνάρτηση keys για να εμφανίσεις μια λίστα με όλα τα κλειδιά.

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

Σημείωσε ότι η keys θα ταξινομήσει τα κλειδιά. Για να πάρεις τα κλειδιά με την αρχική τους σειρά, χρησιμοποίησε τη keys_unsorted.

Δεν υπάρχει αντίστοιχη συνάρτηση για να εμφανίσεις όλες τις τιμές. Ωστόσο, το φίλτρο .[] εμφανίζει τις τιμές του αντικειμένου ως ροή, και αυτή η ροή μπορεί να συλλεχθεί με τον κατασκευαστή πίνακα [...].

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

Επανάληψη

  • Η συνάρτηση map_values(filter) εφαρμόζει το φίλτρο σε κάθε τιμή του αντικειμένου.

    {first: "Jane", last: "Lopez", status: "awesome!"}
    | map_values(ascii_upcase)
    # => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
    
  • Για να επαναλάβεις πάνω σε ένα αντικείμενο, πρέπει πρώτα να το μετατρέψεις σε πίνακα από αντικείμενα κλειδιού-τιμής. Η συνάρτηση to_entries το κάνει αυτό.

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

    Σε αυτό το σημείο, μπορείς να χρησιμοποιήσεις συναρτήσεις επανάληψης πινάκων, όπως τη map.

  • Η συνάρτηση from_entries κάνει το αντίστροφο: μετατρέπει έναν πίνακα από αντικείμενα κλειδιού-τιμής σε αντικείμενο.

    [
      {"key":"name", "value":"Jane"},
      {"key":"age", "value":42}
    ] | from_entries                  # =>{"name": "Jane", "age": 42}
    
  • Για να εφαρμόσεις ένα φίλτρο σε κάθε ζεύγος κλειδιού-τιμής ενός αντικειμένου, χρησιμοποίησε τη συνάρτηση with_entries(filter).

    Για παράδειγμα, με δεδομένο ένα αντικείμενο που αντιστοιχίζει ένα όνομα σε μια ηλικία, τα κλειδιά και οι τιμές μπορούν να αντιστραφούν ως εξής.

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

    εμφανίζει

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

    Η with_entries(filter) είναι το ίδιο με

    to_entries | map(filter) | from_entries
    

Οδηγίες

Σε αυτή την άσκηση, υλοποιείς έναν τρόπο για να παρακολουθείς τα υψηλά σκορ για το πιο δημοφιλές παιχνίδι στην τοπική αίθουσα παιχνιδιών σου.

Έχεις 6 συναρτήσεις να υλοποιήσεις, που σχετίζονται κυρίως με τον χειρισμό ενός αντικειμένου που περιέχει τα υψηλά σκορ.

1. Δημιούργησε έναν νέο πίνακα υψηλών σκορ

Γράψε μια συνάρτηση create_score_board που δημιουργεί ένα αντικείμενο το οποίο χρησιμεύει ως πίνακας υψηλών σκορ. Τα κλειδιά αυτού του αντικειμένου θα είναι τα ονόματα των παικτών, ενώ οι τιμές θα είναι τα σκορ τους. Για σκοπούς δοκιμών, θέλεις να συμπεριλάβεις απευθείας μία καταχώριση στο αντικείμενο. Αυτή η αρχική καταχώριση θα πρέπει να αποτελείται από το "The Best Ever" ως όνομα παίκτη και το 1000000 ως σκορ.

create_score_board
# returns an object with one initial entry

2. Πρόσθεσε παίκτες σε έναν πίνακα υψηλών σκορ

Για να προσθέσεις έναν παίκτη στον πίνακα υψηλών σκορ, υλοποίησε τη συνάρτηση add_player. Δέχεται έναν πίνακα υψηλών σκορ ως είσοδο και χρειάζεται δύο παραμέτρους: το όνομα του παίκτη και το σκορ του παίκτη. Η συνάρτηση επιστρέφει το αντικείμενο του πίνακα υψηλών σκορ με τον νέο παίκτη προσθεμένο.

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

Αν ο παίκτης βρίσκεται ήδη στον πίνακα, επέστρεψε τον πίνακα όπως είναι.

3. Αφαίρεσε παίκτες από έναν πίνακα υψηλών σκορ

Αν οι παίκτες παραβούν τους κανόνες της αίθουσας παιχνιδιών, αφαιρούνται χειροκίνητα από τον πίνακα υψηλών σκορ. Υλοποίησε τη συνάρτηση remove_player, η οποία δέχεται έναν πίνακα ως είσοδο και μία παράμετρο, το όνομα του παίκτη που θα αφαιρεθεί. Αυτή η συνάρτηση θα πρέπει να αφαιρεί την καταχώριση του συγκεκριμένου παίκτη από τον πίνακα και να επιστρέφει τον νέο πίνακα. Αν ο παίκτης δεν βρισκόταν εξαρχής στον πίνακα, δεν θα πρέπει να συμβεί τίποτα στον πίνακα, και θα πρέπει να επιστραφεί όπως είναι.

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

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

4. Αύξησε το σκορ ενός παίκτη

Αν ένας παίκτης ολοκληρώσει άλλο ένα παιχνίδι στην αίθουσα παιχνιδιών, ένα συγκεκριμένο ποσό πόντων θα προστεθεί στο προηγούμενο σκορ του πίνακα. Υλοποίησε τη συνάρτηση update_score, η οποία δέχεται έναν πίνακα υψηλών σκορ ως είσοδο και χρειάζεται δύο παραμέτρους: το όνομα του παίκτη και το ποσό του σκορ που θα προστεθεί. Η συνάρτηση θα πρέπει να επιστρέφει τον πίνακα υψηλών σκορ αφού γίνει η ενημέρωση.

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

Αυτή η συνάρτηση θα πρέπει να προσθέτει τον παίκτη στον πίνακα αν δεν βρισκόταν ήδη σε αυτόν.

5. Εφάρμοσε τους πρόσθετους πόντους της Δευτέρας

Η αίθουσα παιχνιδιών κρατά έναν ξεχωριστό πίνακα υψηλών σκορ τις Δευτέρες. Στο τέλος της ημέρας, κάθε παίκτης σε αυτόν τον πίνακα παίρνει 100 επιπλέον πόντους.

Υλοποίησε τη συνάρτηση apply_monday_bonus. Η συνάρτηση προσθέτει τους πόντους μπόνους για κάθε παίκτη που είναι καταγεγραμμένος σε αυτόν τον πίνακα.

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

6. Βρες το συνολικό σκορ

Διαφορετικές αίθουσες παιχνιδιών συναγωνίζονται μεταξύ τους για να καθορίσουν ποια έχει τους καλύτερους παίκτες. Η αίθουσα με το υψηλότερο συνολικό σκορ κερδίζει τη δόξα.

Γράψε μια συνάρτηση total_score. Δέχεται έναν πίνακα υψηλών σκορ ως είσοδο και επιστρέφει το άθροισμα των σκορ όλων των παικτών.

{
  "Dave Thomas": 44,
  "Freyja Ćirić": 539,
  "José Valim": 265
}
| total_score
# => 848
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
jq Exercism

Έτοιμος να ξεκινήσεις την άσκηση Πίνακας υψηλών βαθμολογιών;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις jq με 12 έννοιες75 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.