Problem overview
The method addContact receives a phone book, a dictionary from names to phone numbers, plus a name and a number. It adds the name with its number and returns the phone book, but only when the name isn't in the book yet. A name that is already there keeps its old number. The order of the entries doesn't matter, and the book can be empty.
Adding "Cara" with "555-0123" to a book with Ana and Ben gives a book with three contacts. Adding "Ben" with a new number changes nothing: Ben keeps "555-0199". Adding "Max" to an empty book gives a book with one contact.
Approach
Assigning to a dictionary key replaces the old value if the key exists, and adds the entry if it doesn't. That is exactly the behaviour we must prevent for existing names, so the assignment goes behind a check. A lookup of a missing key gives nil, so result[name] == nil means "this name is new".
Step by step
- The parameter
phoneBookis a constant. Copy it into a variable,var result = phoneBook. Assigning a dictionary copies it, soresultstarts with the same entries and can change. - Write an
ifthat checksresult[name] == nil. - Inside it, set
result[name] = number. This adds the new entry. - After the
if, returnresult.
The solution in Swift
class Solution {
func addContact(_ phoneBook: [String: String], _ name: String, _ number: String) -> [String: String] {
var result = phoneBook
if result[name] == nil {
result[name] = number
}
return result
}
}
Printing each result with the keys sorted, one key: value pair after another, gives these three lines for the examples:
Ana: 555-0142, Ben: 555-0199, Cara: 555-0123
Ana: 555-0142, Ben: 555-0199
Max: 555-0100
Language details
- The lookup
result[name]has typeString?. Comparing it withnilneeds no unwrapping. - Without the copy,
phoneBook[name] = numberwould not compile, because function parameters are constants. - The caller's dictionary is not touched, since dictionaries are values and
resultis a separate copy. - Dictionary order is not stable, so a program that prints a dictionary should sort the keys first, as above. The lesson's tests do not depend on the order.
Edge cases and common mistakes
- Assigning without the check.
result[name] = numberon its own replaces Ben's number. Example 2 would then return"555-0100"for Ben, which is wrong. - Checking the number instead of the name. Two people can share a number, and the rule is about names. Look up
name. - Returning the original. If you return
phoneBookinstead ofresult, the new contact is missing. - Empty book. No special case: the lookup is
niland the entry is added.
Testing
Try a book where the name is already there but its number is different, such as Ben with "555-0100". The result must still show "555-0199", as in the second example. Then try a number that another contact already has. Adding "Dan" with "555-0142" to a book that holds only Ana with that same number gives Ana: 555-0142, Dan: 555-0142: the new name is added anyway, because only names have to be unique.
It also helps to call the method on a constant book and print that book afterwards. It is unchanged, because the method worked on its own copy.
