Διαδρομές
/
Elm
Elm
/
Ασκήσεις
/
Οι κορυφαίοι σκόρερ
Οι κορυφαίοι σκόρερ

Οι κορυφαίοι σκόρερ

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

Εισαγωγή

Dict

Ένα Dict στην Elm είναι ένα αμετάβλητο λεξικό από μηδέν ή περισσότερα ζεύγη κλειδιού-τιμής.

Τα λεξικά χειρίζονται με συναρτήσεις και τελεστές που ορίζονται στο module Dict.

Οι σχολιασμοί τύπων για τα λεξικά γράφονται ως εξής

Dict String (List Int) --> a dict with String keys and List Int values
Dict Int String --> a dict with Int keys and String values

Τα λεξικά μπορούν να δημιουργηθούν ως εξής:

empty : Dict Int String
empty = Dict.empty

singleValue = Dict.singleton 5 "Value for key 5" --> Dict Int String

twoValues = Dict.fromList [ ( "Alice", 0 ), ( "Bob", 1 ) ] --> Dict String Int

Τα στοιχεία μπορούν να ανακτηθούν με τη get. Καθώς ένα κλειδί μπορεί να υπάρχει ή να μην υπάρχει στο λεξικό, το αποτέλεσμα θα είναι τυλιγμένο σε ένα Maybe.

alice = Dict.fromList [ ( 0, "Alice" ) ]
keyExists = Dict.get 0 alice --> Just "Alice"
keyNotPresent = Dict.get 1 alice --> Nothing

Τα στοιχεία μπορούν να προστεθούν με τη insert. Τα στοιχεία για κλειδιά που υπάρχουν ήδη στο λεξικό αντικαθίστανται.

alice = Dict.fromList [ ( "Alice", 0 ) ]
aliceAndBob = Dict.insert "Bob" 1 alice  --> Dict.fromList [ ( "Alice", 0 ), ( "Bob", 1 ) ]
aliceAndAlice = Dict.insert "Alice" 1 alice  --> Dict.fromList [ ( "Alice", 1 ) ]

Τα στοιχεία μπορούν να ενημερωθούν με τη update. Αν το κλειδί δεν υπάρχει, η συνάρτηση ενημέρωσης θα κληθεί με Nothing.

alice = Dict.fromList [ ( 0, "Alice" ) ]
aliceUpperCase = Dict.update 0 (Maybe.map String.toUpper) alice --> Dict.fromList [ ( 0, "ALICE" ) ]
aliceNoCase = Dict.update 0 (\_ -> Nothing) alice --> Dict.empty
bobUpperCase = Dict.update 1 (\_ -> Just "BOB") alice --> Dict.fromList [ ( 0, "Alice" ), ( 1, "BOB" ) ]
bobNoCase = Dict.update 1 (\_ -> Nothing) alice --> Dict.fromList [ ( 0, "Alice" ) ]

Τα στοιχεία μπορούν να αφαιρεθούν με τη remove. Αν το κλειδί δεν υπάρχει, δεν γίνεται καμία αλλαγή.

alice = Dict.fromList [ ( 0, "Alice" ) ]
stillAlice = Dict.remove 1 --> ( 0, "Alice" )
empty = Dict.remove 0 alice --> Dict.empty

Μια λίστα από ζεύγη κλειδιού-τιμής μπορεί να μετατραπεί σε λεξικό με τη fromList.

alice = Dict.fromList [ ( 0, "Bob" ), ( 0, "Alice" ) ]
--> True Dict.fromList [ ( 0, "Alice" ) ]

Τα στοιχεία μπορούν να μετατραπούν σε λίστα με τη toList. Η λίστα είναι ταξινομημένη κατά κλειδιά.

aliceAndBob = Dict.fromList [ ( 1, "Alice" ), ( 0, "Bob" ) ]
bobAndAlice = Dict.toList aliceAndBob
--> [ ( 0, "Bob" ), ( 1, "Alice" ) ]

Πολλαπλά στοιχεία μπορούν να αφαιρεθούν με τη filter.

aliceAndBob = Dict.fromList [ ( "Alice", 1 ), ( "Bob", 0 ) ]
bob = Dict.filter (\name count -> name == "Bob") aliceAndBob --> Dict.fromList [ ( "Bob", 0 ) ]

Τα στοιχεία μπορούν να μετασχηματιστούν με τη map.

alice = Dict.fromList [ ( "Alice", 0 ) ]
empty = Dict.map (\player count -> count + 1) alice --> Dict.fromList [ ( "Alice", 1 ) ]

Τα λεξικά μπορούν να συνδυαστούν / μετασχηματιστούν με τη merge.

aliceAndBob = Dict.fromList [ ( "Alice", 1 ), ( "Bob", 1 ) ]
bobAndCedd = Dict.fromList [ ( "Bob", 1 ), ( "Cedd", 1 ) ]
firstDictCountsDouble = Dict.merge
        -- when only in aliceAndBob
        (\name count mergedCounts -> Dict.insert name (2 * count) mergedCounts)
        -- when in aliceAndBob and bobAndCedd
        (\name aliceAndBobCount bobAndCeddCount mergedCounts -> Dict.insert name (2 * aliceAndBobCount + bobAndCeddCount) mergedCounts)
        -- when only in bobAndCedd
        (\name count mergedCounts -> Dict.insert name count mergedCounts)
        -- the two dicts to merge
        aliceAndBob
        bobAndCedd
        -- the initial state of the merge
        Dict.empty
--> Dict.fromList [ ( "Alice", 2 ), ( "Bob", 3 ), ( "Cedd", 1 ) ]

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

Στην Elm, είναι γενικά καλύτερα να χρησιμοποιείς αφαιρέσεις υψηλότερου επιπέδου, όπως τις Dict.map, Dict.filter και Dict.merge, αντί για αφαιρέσεις χαμηλότερου επιπέδου, όπως τις Dict.get και Dict.remove, αν και φυσικά αυτό εξαρτάται από το πλαίσιο.

Οδηγίες

Η αποστολή σου είναι να πάρεις μια λίστα με τους σκόρερ ενός αγώνα και να μετρήσεις πόσα γκολ έχει βάλει κάθε παίκτης.

Το PlayerName είναι ένα ψευδώνυμο τύπου για το String, ώστε ο κώδικας να διαβάζεται πιο εύκολα και να ξεχωρίζει αυτή η χρήση του String από άλλες χρήσεις του String.

1. Συγκέντρωσε τους σκόρερ

Πρώτα υλοποίησε την updateGoalCountForPlayer, ώστε να αρχικοποιεί ή να αυξάνει τον αριθμό γκολ ενός παίκτη. Έπειτα υλοποίησε τη συνάρτηση aggregateScorers, ώστε να μετράς πόσα γκολ έχει βάλει κάθε παίκτης, χρησιμοποιώντας την updateGoalCountForPlayer. Αυτή η συνάρτηση δέχεται μια List PlayerName (τα ονόματα των παικτών που έβαλαν τα γκολ, που μπορεί να περιέχει διπλότυπα ονόματα παικτών) και επιστρέφει ένα Dict PlayerName Int που περιέχει όλους τους παίκτες της λίστας μαζί με το πόσα γκολ έχουν βάλει.

aggregateScorers [ "Betty", "Cedd", "Betty" ]
--> Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ]

2. Αφαίρεσε τους ασήμαντους παίκτες

Υλοποίησε τη συνάρτηση removeInsignificantPlayers, για να φιλτράρεις όσους παίκτες έχουν βάλει λιγότερα γκολ από το όριο.

removeInsignificantPlayers 2 (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> Dict.fromList [ ( "Betty", 2 ) ]

3. Μηδένισε τον αριθμό γκολ ενός παίκτη

Υλοποίησε τη συνάρτηση resetPlayerGoalCount, ώστε να μηδενίζει τα γκολ που έχει βάλει ένας παίκτης.

resetPlayerGoalCount "Cedd" (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 0 ) ]

4. Μορφοποίησε τον αριθμό γκολ για έναν παίκτη

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

formatPlayer "Betty" (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> "Betty: 2"

5. Μορφοποίησε τον αριθμό γκολ για όλους τους παίκτες

Υλοποίησε τη συνάρτηση formatPlayers, ώστε να μορφοποιείς τον αριθμό γκολ όλων των παικτών ως συμβολοσειρά. Οι παίκτες πρέπει να είναι ταξινομημένοι κατά όνομα παίκτη.

formatPlayers (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
--> "Betty: 2, Cedd: 1"

6. Συνδύασε τους αγώνες

Υλοποίησε τη συνάρτηση combineGames, μετρώντας τον συνολικό αριθμό γκολ που έχει βάλει κάθε παίκτης και στους δύο αγώνες.

combine Games
  (Dict.fromList [ ( "Betty", 2 ), ( "Cedd", 1 ) ] )
  (Dict.fromList [ ( "Betty", 2 ), ( "Mario", 3 ) ] )
--> Dict.fromList [ ( "Betty", 4 ), ( "Cedd", 1 ), ( "Mario", 3 ) ]
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Elm Exercism

Έτοιμος να ξεκινήσεις την άσκηση Οι κορυφαίοι σκόρερ;

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