Problem overview
The method countVote receives votes, a dictionary from names to how many votes each person has, and the name on a new vote. It counts the vote and returns the dictionary. 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.
With Ana at 3 and Ben at 5, a vote for Ana gives Ana at 4. A vote for Cara, who isn't in the dictionary, gives Cara at 1. In an empty dictionary, the first vote for Max gives Max at 1.
Approach
The new count is "the old count plus one", where the old count of a missing name is 0. The default: subscript says exactly that: result[name, default: 0] gives the stored count, or 0 when the name has no entry. Adding 1 and storing the result covers both cases with no if.
Step by step
- Copy the parameter into a variable:
var result = votes. Parameters are constants in Swift, and assigning a dictionary copies it. - Read the current count into
countwithresult[name, default: 0]. The result is a plainInt, not an optional. - Set
result[name] = count + 1. For a new name this adds the key. For an existing name it replaces the old count. - Return
result.
The solution in Swift
class Solution {
func countVote(_ votes: [String: Int], _ name: String) -> [String: Int] {
var result = votes
let count = result[name, default: 0]
result[name] = count + 1
return result
}
}
Printing each result as sorted key: value pairs gives:
Ana: 4, Ben: 5
Ana: 3, Ben: 5, Cara: 1
Max: 1
Language details
- A plain
result[name]would be anInt?, andresult[name] + 1would not compile. The default turns the optional into a plain number. - Reading with a default doesn't add the key. The key appears only at the assignment.
- The two lines can be shortened to
result[name, default: 0] += 1. It does the same read, add and store in one step, and it works because the subscript with a default can be written to as well. The lesson splits it so each step is visible.
Edge cases and common mistakes
- Using
!on the lookup.result[name]!crashes the program for a new name, such as Cara. - Assigning 1 always. That would reset Ana to 1 instead of 4.
- Forgetting to store. Computing
count + 1without writing it back leaves the dictionary unchanged. - Changing the parameter. Writing to
votesdirectly doesn't compile. Use the copy.
Think of the dictionary as a tally sheet: a person with no marks yet has no line on it, and the first mark creates the line. That is why a missing name and the number 0 mean the same thing here.
Testing
- Two votes in a row for the same new name: calling the method once on an empty dictionary and then again on its result, both for
"Zoe", givesZoe: 2. - A vote for Ben in
["Ana": 3, "Ben": 5, "Cleo": 1]givesAna: 3, Ben: 6, Cleo: 1. Only Ben's count changes.
The one-line form gives the same results: starting from Ana at 3, r["Ana", default: 0] += 1 and r["Cara", default: 0] += 1 end with Ana: 4, Cara: 1.
