Start learning free

LESSON 137 OF 675 · DICTIONARIES - CHALLENGES

Count a Vote in TypeScript: Default Count with in

Practice Read the full explanation

You get votes, a dictionary from names to how many votes each person has. You also get the name on a new vote.

Count the new vote and return votes.

The person called name gets one more vote. A name with no votes yet isn't in votes. It starts from 0, so after this vote it has 1. The order of the entries doesn't matter.

 

Example 1:

Input: votes = {"Ana": 3, "Ben": 5}, name = "Ana"
Output: {"Ana": 4, "Ben": 5}
Explanation: Ana had 3 votes. Now she has 3 + 1 = 4.

Example 2:

Input: votes = {"Ana": 3, "Ben": 5}, name = "Cara"
Output: {"Ana": 3, "Ben": 5, "Cara": 1}
Explanation: Cara had no votes yet. She starts from 0 and now has 1.

Example 3:

Input: votes = {}, name = "Max"
Output: {"Max": 1}
Explanation: This is the very first vote. Max now has 1.

 

Constraints:

  • votes can be empty.
  • Every count in votes is at least 1.
  • Names are single words made of English letters.
STEP 1 OF 4
    Ctrl + Enter to check

    TYPESCRIPT · DICTIONARIES - CHALLENGES

    Count A Vote in TypeScript, explained

    Problem overview

    countVote receives votes, an object from names to how many votes each person has, and the name on a new vote. The person called name gets one more vote, and the function returns votes. A name with no votes yet isn't a key. It starts from 0, so after its first vote it has 1. The order of the entries doesn't matter.

    With {"Ana": 3, "Ben": 5} and "Ana", Ana goes from 3 to 4. With "Cara", who isn't a key, she is added with 1. With an empty object and "Max", the result is {"Max": 1}.

    Approach

    The difficulty is the person with no votes. Reading a missing key does not give 0. It gives undefined, and undefined + 1 is NaN. So start a local count at 0, and replace it with the stored count only when the key exists. Then one assignment, count + 1, handles both cases.

    Step by step

    1. Start the count at 0. A number variable named count, declared with let because it may change.
    2. Read the old count if there is one. If name in votes, set count to votes[name]. A missing name leaves the 0.
    3. Store the new count. votes[name] = count + 1. For a new name this adds the key with 1, and for an existing one it replaces the old count.
    4. Return votes. Only the entry of name changed.

    The solution in TypeScript

    class Solution {
        countVote(votes: { [key: string]: number }, name: string): { [key: string]: number } {
            let count: number = 0;
            if (name in votes) {
                count = votes[name];
            }
            votes[name] = count + 1;
            return votes;
        }
    }

    The three examples print:

    { Ana: 4, Ben: 5 }
    { Ana: 3, Ben: 5, Cara: 1 }
    { Max: 1 }

    Tracing the second example

    For {"Ana": 3, "Ben": 5} and "Cara", count starts at 0. "Cara" in votes is false, so the if body is skipped and count is still 0. The assignment then stores 0 + 1 = 1 under "Cara", which creates the key. For "Ana" the if body runs first and sets count to 3, so the same assignment stores 3 + 1 = 4.

    That is the value of the pattern: one assignment at the end serves both the new name and the existing one, and only the starting value differs.

    Why check with in and not with the value?

    A tempting shortcut is if (votes[name]). It happens to work here, because the constraints say every stored count is at least 1, so a stored count is never falsy. It would break on a dictionary that can hold 0. The in check asks the exact question, "is this a key?", and stays correct whatever values the dictionary holds.

    Edge cases and common mistakes

    • The first vote. Without the default, votes["Max"] += 1 on an empty object leaves { Max: NaN }. The type says the value is a number, but types are erased when the code is compiled, so the compiler does not notice.
    • Overwriting with 1. Writing votes[name] = 1 unconditionally would reset Ana to 1.
    • Declaring count after the if. It would replace the value just read. The default goes first.
    • Using const for count. A const cannot be reassigned inside the if, so use let.
    • Short form. votes[name] = (votes[name] ?? 0) + 1 does the same job in one line: it gives { Ana: 4, Ben: 5 }, { Ana: 3, Cara: 1 } and { Max: 1 } for names that exist, are new, or start an empty object. The lesson spells the default out so that each step is visible.
    Keep going with TypeScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free