Start learning free

LESSON 265 OF 671 · DESTRUCTURING, SORTING & BUILT-INS

Leaderboard in JavaScript: Sorting Pairs by Score

Practice Read the full explanation

You get an array of players, players. Each player is a pair: a name and a score, like ("Ava", 30).

Return the names, from the highest score to the lowest.

Players with the same score go in alphabetical order of their names.

The starter code shows how your language holds a pair.

 

Example 1:

Input: players = [("Ava", 30), ("Ben", 25), ("Cy", 40)]
Output: ["Cy", "Ava", "Ben"]
Explanation: Cy has the most points, 40.
Then come Ava with 30 and Ben with 25.

Example 2:

Input: players = [("Mia", 50), ("Leo", 70), ("Ava", 50)]
Output: ["Leo", "Ava", "Mia"]
Explanation: Leo leads with 70.
Ava and Mia both have 50.
Ava comes first from A to Z.

Example 3:

Input: players = [("Zoe", 0)]
Output: ["Zoe"]
Explanation: Zoe is the only player.

 

Constraints:

  • players has 1 to 100 players.
  • Every score is a whole number from 0 to 1000.
  • Each name is a capital letter followed by lowercase letters, like "Ava".
  • No two players have the same name.
STEP 1 OF 6
    Ctrl + Enter to check

    JAVASCRIPT · DESTRUCTURING, SORTING & BUILT-INS

    Leaderboard in JavaScript, explained

    Problem overview

    leaderboard(players) receives an array of players. Each player is a two-item array, [name, score], such as ["Ava", 30]. The function returns just the names, from the highest score to the lowest. Players with the same score go in alphabetical order of their names.

    For [["Ava", 30], ["Ben", 25], ["Cy", 40]] the answer is ["Cy", "Ava", "Ben"]. For [["Mia", 50], ["Leo", 70], ["Ava", 50]] it is ["Leo", "Ava", "Mia"]: Leo leads with 70, and Ava and Mia tie at 50, so Ava comes first.

    Approach

    There are two jobs: put the players in order, then keep only the names. The order comes from sort with a compare function that has two rules, like the previous sorting exercises:

    1. If the scores differ, the higher score goes first. For a descending order, return b[1] - a[1]. It is negative when a has more points, so a goes first.
    2. If the scores are equal, compare the names with a[0].localeCompare(b[0]).

    Writing a[1] - b[1] instead would give lowest first, so the order of a and b in the subtraction is what flips the direction.

    Step by step

    1. Call players.sort with a compare function of a and b. Its first line returns b[1] - a[1] when the scores differ.
    2. Below that line, return a[0].localeCompare(b[0]) for equal scores.
    3. Start an empty array, names.
    4. Loop over the sorted players with for (const [name, score] of players). The square brackets unpack each pair into name and score.
    5. Inside the loop, push name onto names.
    6. After the loop, return names.

    The solution in JavaScript

    class Solution {
        leaderboard(players) {
            players.sort((a, b) => {
                if (a[1] !== b[1]) {
                    return b[1] - a[1];
                }
                return a[0].localeCompare(b[0]);
            });
            let names = [];
            for (const [name, score] of players) {
                names.push(name);
            }
            return names;
        }
    }
    

    The loop never uses score, but the pair has two parts, so the destructuring names both. By then the players are sorted, so pushing the names one by one gives them in leaderboard order. The three examples return:

    ["Cy","Ava","Ben"]
    ["Leo","Ava","Mia"]
    ["Zoe"]
    

    Sorting changes the array that was passed in. After the call on the second example, players itself is [["Leo",70],["Ava",50],["Mia",50]].

    Reading the compare function

    The function decides only which of two players goes first. Trying it on a few pairs from the second example gives these results:

    compare(["Leo",70], ["Mia",50])  -> -20   (Leo goes first)
    compare(["Mia",50], ["Leo",70])  ->  20   (Leo goes first)
    compare(["Mia",50], ["Ava",50])  ->  1    (same score, Ava goes first)
    

    Only the sign matters. A negative number keeps a before b, and a positive number puts b first.

    Another way to collect the names

    The loop can be replaced by map. After the sort, return players.map(([name]) => name); gives the same names. The lesson uses the loop so the unpacking in for (const [name, score] of players) gets practice.

    Why two rules in one function

    A single compare function can express a "sort by this, then by that" order by checking the main key first and falling back to the second key only when the first key is equal. That is exactly what the if does here: it returns early whenever the scores differ, so the name comparison only runs for players who tie. The names are all different, so the second rule always gives a clear order and never needs a third.

    Edge cases and common mistakes

    • Wrong direction. a[1] - b[1] sorts lowest first. On the first example it gives ["Ben", "Ava", "Cy"].
    • Missing tie-break. Sorting by score alone on the second example gives ["Leo", "Mia", "Ava"], because Mia was before Ava in the input and ties keep their input order. The tests expect Ava first.
    • Returning pairs. The function returns only names.
    • One player. A single pair like ["Zoe", 0] sorts to itself and gives ["Zoe"].
    Keep going with JavaScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free