Start learning free

LESSON 228 OF 678 · LOOPS WITH STRINGS, ARRAYS & DICTIONARIES

Top Scorer in Swift: Best So Far in a Dictionary Loop

Practice Read the full explanation

You get scores, a Dictionary from players' names to their scores. Return the name of the player with the highest score.

Several players may share the highest score. Then return the name that comes first in alphabetical order.

 

Example 1:

Input: scores = {"Ana": 90, "Ben": 75, "Cara": 88}
Output: "Ana"
Explanation: 90 is the highest score, and it is Ana's.

Example 2:

Input: scores = {"Zoe": 82, "Ana": 82}
Output: "Ana"
Explanation: Both have 82. "Ana" comes before "Zoe" in alphabetical order.

Example 3:

Input: scores = {"Max": 0}
Output: "Max"
Explanation: Max is the only player, so his score is the highest.

 

Constraints:

  • scores has at least one name.
  • Every score is a whole number from 0 to 100.
  • Each name is a capital letter followed by lowercase letters, like "Ana".
STEP 1 OF 5
    Ctrl + Enter to check

    SWIFT · LOOPS WITH STRINGS, ARRAYS & DICTIONARIES

    Top Scorer in Swift, explained

    Problem overview

    The function topScorer receives scores, a [String: Int] dictionary from players' names to scores. It returns the name of the player with the highest score. If several players share the highest score, it returns the one whose name comes first alphabetically. The dictionary always has at least one name, and every score is between 0 and 100.

    For ["Ana": 90, "Ben": 75, "Cara": 88] the answer is "Ana". For ["Zoe": 82, "Ana": 82] both players have 82, so the answer is "Ana". For ["Max": 0] the answer is "Max".

    Approach: keep the best player so far

    You look at every entry once and remember the best one seen up to now. Each new player either beats the current best or doesn't. When the loop ends, the one remembered is the answer.

    The one trap is the order. A Swift dictionary has no fixed order, and it can change between runs. A solution that returns "the first player with the top score" would give different answers on different runs. The tie rule fixes that: because the alphabetically first name wins, the answer is the same whatever order the loop uses.

    A player beats the best so far in two cases: a higher score, or the same score and a name that comes earlier. In Swift, name < bestName on two strings is true when name sorts before bestName. All names here are a capital letter followed by lowercase ones, so the comparison matches alphabetical order.

    Step by step

    1. Set up the best so far. bestName starts as an empty string and bestScore as -1, both with var. Every real score is at least 0, so the first player visited always beats -1.
    2. Loop over the entries. for (name, score) in scores splits each entry into its key and its value.
    3. Test the player. The condition is a higher score, or an equal score with an earlier name. The tie check goes in parentheses so that it counts only when the scores are equal.
    4. Update the best. Inside the if, store the name and score.
    5. Return bestName after the loop.

    The solution in Swift

    class Solution {
        func topScorer(_ scores: [String: Int]) -> String {
            var bestName = ""
            var bestScore = -1
            for (name, score) in scores {
                if score > bestScore || (score == bestScore && name < bestName) {
                    bestName = name
                    bestScore = score
                }
            }
            return bestName
        }
    }
    

    Swift details worth knowing:

    • && binds tighter than ||, so the parentheses are not required by the compiler. They make the intent clear to a reader.
    • The loop needs the empty string and -1 as starting values because Swift has no "no value yet" for a plain String or Int. The -1 works because scores can't be negative.
    • The function returns a String, not an optional, which is fine because the dictionary always has at least one name.

    Tests

    On the three examples the function returns:

    Ana
    Ana
    Max
    

    Another case: ["Ana": 5, "Ben": 5, "Al": 5] returns Al, since "Al" sorts before "Ana".

    Common mistakes

    • Starting bestScore at 0. A dictionary where everyone has 0, such as ["Max": 0], would then never beat the start value, and the function would return an empty string.
    • Forgetting the tie rule. With only score > bestScore, the winner of a tie is whichever entry the loop happens to reach first, so the result can change from run to run.
    • Dropping the parentheses logic. score == bestScore && name < bestName must both be true. Checking the names alone would pick a lower-scoring player with an earlier name.
    • Returning inside the loop. The best player is only known after every entry has been compared.
    Keep going with Swift500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free